package com.apes.fn.business.fixedLoss.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.crm.business.model.InsuranceCompany;
import com.apes.crm.business.model.InsuranceCompanyDetail;
import com.apes.crm.business.repository.InsuranceCompanyDetailRepository;
import com.apes.fn.business.carAccident.modle.CarAccident;
import com.apes.fn.business.carAccident.repository.CarAccidentRepository;
import com.apes.fn.business.carAccident.service.CarAccidentService;
import com.apes.fn.business.fixedLoss.modle.*;
import com.apes.fn.business.fixedLoss.repository.*;
import com.apes.fn.crm.customer.FnAppCustomerService;
import com.apes.fn.crm.customerExpand.FnCustomerExpand;
import com.apes.fn.mdm.purchase.PurchasingGroup;
import com.apes.fn.mdm.purchase.PurchasingGroupRepository;
import com.apes.fn.pi.fnCommunal.FnCommunalService;
import com.apes.fn.scm.commodityInquiry.model.CommodityInquiryItem;
import com.apes.fn.scm.commodityInquiry.service.CommodityInquiryOrderService;
import com.apes.fn.scm.insuranceRules.InsuranceRule;
import com.apes.fn.scm.insuranceRules.InsuranceRuleRepository;
import com.apes.fn.scm.insuranceRules.InsuranceRuleService;
import com.apes.fn.scm.merchant.settlement.service.FeeRateService;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.model.RetailOrderPayMethod;
import com.apes.fn.scm.retailOrder.repository.RetailOrderRepository;
import com.apes.fn.scm.retailOrder.service.RetailOrderFnExpenseOrderService;
import com.apes.fn.server.pickUpCar.model.PickUpCar;
import com.apes.fn.server.pickUpCar.repository.PickUpCarRepository;
import com.apes.fn.server.productRequire.ProductRequire;
import com.apes.fn.server.productRequire.ProductRequireItem;
import com.apes.fn.server.productRequire.ProductRequireRepository;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.servicePlan.repository.ServicePlanDao;
import com.apes.fn.server.servicePlan.repository.ServicePlanRepository;
import com.apes.fn.server.servicePlan.service.AbstractPlan;
import com.apes.fn.server.servicePlan.service.ServicePlanceService;
import com.apes.fn.server.servicePlan.service.ServiceToForeign;
import com.apes.fn.tms.repository.SiteRepository;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.jpa.logger.ApesLoggerService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.plugin.outbox.OutboxEventService;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.OutboxSubscriberService;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.plugin.soe.metadata.BusinessAttributeValue;
import com.apes.framework.plugin.soe.store.database.repository.BusinessAttributeValueRepository;
import com.apes.framework.plugin.todo.TodoTaskService;
import com.apes.framework.util.*;
import com.apes.pi.service.PiManager;
import com.apes.scm.account.account.model.Stock;
import com.apes.scm.account.account.repository.StockRepository;
import com.apes.scm.masterdata.area.model.Area;
import com.apes.scm.masterdata.car.model.CarConfiguration;
import com.apes.scm.masterdata.car.model.CarLabel;
import com.apes.scm.masterdata.car.model.CarModel;
import com.apes.scm.masterdata.car.repository.CarConfigurationRepository;
import com.apes.scm.masterdata.contrast.model.ContrastPartyCode;
import com.apes.scm.masterdata.contrast.repository.ContrastPartyCodeRepository;
import com.apes.scm.masterdata.enumeration.model.BusinessParam;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.enumeration.repository.BusinessParamRepository;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.ChannelRepository;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.frame.repository.StoreRepository;
import com.apes.scm.masterdata.party.model.CompanyEntry;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.CompanyEntryRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.party.service.PartyRoleService;
import com.apes.scm.masterdata.product.model.Classify;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.masterdata.product.model.ServeType;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import com.apes.scm.masterdata.product.repository.ProductUomRepository;
import com.apes.scm.masterdata.product.service.ProductNegativeSellingService;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.model.PhyDepot;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import com.apes.scm.masterdata.stock.service.LocationService;
import com.apes.scm.rbac.model.Post;
import com.apes.scm.rbac.model.User;
import com.apes.scm.rbac.repository.PostRepository;
import com.apes.scm.rbac.repository.UserRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.*;

/**
 * @ClassName : LossQuotationService
 * @Description : 定损报价单业务层
 * @Author : WSJ
 * @Date: 2020-03-13 11:33
 */
@Service("lossQuotationService")
public class LossQuotationService extends AbstractPlan {
    @Autowired
    private LossQuotationRepository lossQuotationRepository;
    @Autowired
    private PostRepository postRepository;
    @Autowired
    private LossQuotationDao lossQuotationDao;
    @Autowired
    private LossQuotationItemRepository lossQuotationItemRepository;
    @Autowired
    private ServicePlanceService servicePlanceService;
    @Autowired
    private ServiceToForeign serviceToForeign;
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private ProductUomRepository productUomRepository;
    @Autowired
    private LocationRepository locationRepository;
    @Autowired
    private FnCommunalService fnCommunalService;
    @Autowired
    private CarAccidentRepository carAccidentRepository;
    @Autowired
    private OutboxSubscriberService outboxSubscriberService;
    @Autowired
    private LossAssessmentGoodsRepository assessmentGoodsRepository;
    @Autowired
    private DeptRepository deptRepository;
    @Autowired
    private ServicePlanRepository servicePlanRepository;
    @Autowired
    private EnumerationRepository enumerationRepository;
    @Autowired
    private LossQuotationPlanRepository lossQuotationPlanRepository;
    @Autowired
    private LossReceivedApportionService lossReceivedApportionService;
    @Autowired
    private LossReceivedItemRepository lossReceivedItemRepository;
    @Autowired
    private LossReceivedApportionRepository lossReceivedApportionRepository;
    @Autowired
    private ServicePlanDao servicePlanDao;
    @Autowired
    private ProductNegativeSellingService productNegativeSellingService;
    @Autowired
    private ProductRequireRepository productRequireRepository;
    @Autowired
    private ApesLoggerService apesLoggerService;

    public LossQuotation save(SimpleRequest request) throws RuntimeException {
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        checkGoods(lossQuotation.getLossQuotationItems());
        checkCarInfo(lossQuotation);
        checkGoodsWithZeroQty(lossQuotation);
        updateCarAccident(lossQuotation,1);
        lossQuotation.computeAmount();
        lossQuotation.setState("create");
        lossQuotation.setBusinessTypeName("定损报价单");
        String getCarType = getGetCarType(lossQuotation);
        lossQuotation.setGetCarType(getCarType);
        parsingReturnRatio(lossQuotation);
        checkInsuranceRule(lossQuotation.getInsuranceCompany(),lossQuotation.getFixedLossDept() );
        parsingDividendRatio(lossQuotation);
        recordEditHistory(lossQuotation, request);
        lossQuotation = lossQuotationRepository.saveAndFlush(lossQuotation);
        updateCarEvaluation(lossQuotation);
        return  lossQuotation;
    }

    private void checkCarInfo(LossQuotation lossQuotation) {
        if (lossQuotation.getCarModel()!=null&&lossQuotation.getCarConfiguration()!=null&&lossQuotation.getCarLabel()!=null)return;
        FnCustomerExpand fnCustomerExpand = lossQuotation.getCustomerExpand();
        if (fnCustomerExpand==null)return;
        CarConfiguration carConfiguration = SpringManager.getBean(CarConfigurationRepository.class).findOne(fnCustomerExpand.getJekunModelCode());
        if (carConfiguration==null) return;
        CarModel carModel = carConfiguration.getCarModel();
        CarLabel carLabel = carConfiguration.getCarLabel();
        lossQuotation.setCarModel(carModel);
        lossQuotation.setCarLabel(carLabel);
        lossQuotation.setCarConfiguration(carConfiguration);
    }

    /**
     * 检查基地是否有定损资质
     * @param insuranceCompany 保险公司
     * @param company 基地公司
     */
    public  void  checkInsuranceRule (InsuranceCompany insuranceCompany,PartyRole company) {
        if (!insuranceCompany.isCooperation())return;
        SpringManager.getBean(InsuranceRuleRepository.class)
                .findAll(JpaDsl.toCriteria(MapUtil.mapper("insuranceCompany.id", insuranceCompany.getId(),
                        "company.id", company.getId(),"valid",true)))
                .stream().findFirst().orElseThrow( () -> new RuntimeException("该基地无定损资质,请从新选择基地!!!") );
    }
    /**
     * 检查基地是否有定损资质
     * @param insuranceCompany 保险公司
     * @param dept 基地门店
     */
    public  void  checkInsuranceRule (InsuranceCompany insuranceCompany,Dept dept) {
        if (!insuranceCompany.isCooperation())return;
        InsuranceRule insuranceRule = SpringManager.getBean(InsuranceRuleService.class)
                .findByDeptAndInsuranceCompany(dept, insuranceCompany);
        if (Objects.isNull(insuranceRule)) throw new RuntimeException("该基地无定损资质,请从新选择基地!!!");
    }
    /**
     * 更新评估信息
     * @param lossQuotation
     */
    private void updateCarEvaluation(LossQuotation lossQuotation) {
        try {
            CarAccident carAccident = carAccidentRepository.findOne(lossQuotation.getCarAccident());
            carAccident.getCarEvaluations().setClaimType(lossQuotation.getClaimType());
            carAccidentRepository.saveAndFlush(carAccident);
        } catch (Exception e) {
            throw new RuntimeException("定损评估信息为空,请先去车险报案单界面填写评估信息!!!");
        }
    }

    /**
     * 更新车险报案单状态
     * @param lossQuotation
     */
    public void updateCarAccident(LossQuotation lossQuotation,int index) {
        //index 回写标识 : 1 : 转定损 2: 转门店
        CarAccident carAccident =carAccidentRepository.findOne(lossQuotation.getCarAccident());
        if (carAccident == null ) {
            throw new RuntimeException("未找到对应的车险报案单号!!1");
        }
        if (Objects.isNull(carAccident.getCarEvaluations())){
            throw new RuntimeException("请先填写车险报案单得评估信息,再做定损报价单!!!");
        }
        switch (index) {
            case 1 :
                carAccident.setState("fixedLoss");
                carAccident.setFixedLossDate(new Date());
                break;
            case 2 :
                List<PickUpCar> approve = SpringManager.getBean(PickUpCarRepository.class).findByLicenseNumberAndDeptAndState(carAccident.getCarNumber(), carAccident.getDept(), "approve");
                if (approve.isEmpty())carAccident.setState("store");
                if (!approve.isEmpty())carAccident.setState("inStore");
                break;
            default:
                throw new RuntimeException("无对应标识!!!");
        }
        carAccidentRepository.saveAndFlush(carAccident);
//        if (index==1)SpringManager.getBean(CarAccidentService.class).carAccidentSaveToApp(SpringManager.getBean(CarAccidentService.class).getAppSaveParam(carAccident));

    }

    public boolean judgeToTechnical(LossQuotation lossQuotation){

        //存在非快速服务商品
        Set set = lossQuotation.getLossQuotationItems().stream().filter(
                (item)-> !item.getProduct().isFreeServiceValid() && item.getProduct().getClassify().getId().startsWith("S01")
        ).collect(toCollection(HashSet::new));
        if(set.size() > 0) return true;

        // throw new RuntimeException("定损明细商品都是快速服务商品,不需要转技术审核!!!!") ;

        //当定损报价单只有配件且配件中有全车件
        set = lossQuotation.getLossQuotationItems().stream().filter(
                (item)->{
                    return item.getProduct().getCategory() != null &&
                            (item.getProduct().getClassify().getId().startsWith("M010303")
                                    || item.getProduct().getClassify().getId().startsWith("M010304") );
                }
        ).collect(toCollection(HashSet::new));
        return set.size() > 0;
        // throw new RuntimeException("该定损单无全车件商品,不需要转技术审核!!!!") ;
    }

    public LossQuotation update(SimpleRequest request) {
        checkData(request);
        LossQuotation lossQuotation = request.getO(LossQuotation.class);

        checkGoods(lossQuotation.getLossQuotationItems());
        checkGoodsWithZeroQty(lossQuotation);
        checkCarInfo(lossQuotation);

        // checkChangeOrderType(lossQuotation);
        recordEditHistory(lossQuotation, request);

        if (lossQuotation.getReturnRatio() <= 0) {
            parsingReturnRatio(lossQuotation);
        }
        checkDividendApprove(lossQuotation,request);
        LossQuotation quotation = lossQuotationRepository.findOne(lossQuotation.getId());
        if ("confirmPlan".equals(quotation.getState())) {
            if (lossQuotation.getTotalAmount() <= 0) throw new RuntimeException("定损总金额不能为零!!!");
            lossQuotation.computeAmount();
            if (!lossQuotation.checkAmount()) throw new RuntimeException("定损总金额与明细定损金额不相等,请检查!!!");

        }else {
            lossQuotation.computeAmount();
        }

        List<LossQuotationPlan> list = lossQuotation.getLossQuotationPlans().stream().filter(item -> item.getFixedLossPrice() == 0).collect(toList());
        if (list.size() >0) throw new RuntimeException("定损确认方案的定损金额不能为零!!!");

        //循环计算 每个商品得毛利率
        for (LossQuotationPlan lossQuotationPlan : lossQuotation.getLossQuotationPlans()) {
            lossQuotationPlan.computeProfit();
        }

        try {
            lossQuotation.getLossQuotationItems().forEach(
                    item -> {
                        if (!item.isAgree()) {
                            item.setService(false);
                            item.setInsurance(false);

                        }
                    });

            lossQuotation.setTypeBusinesses(lossQuotation.getTypeBusinesses());
            String getCarType = getGetCarType(lossQuotation);
            lossQuotation.setGetCarType(getCarType);
            lossQuotation = lossQuotationRepository.saveAndFlush(lossQuotation);
        } catch (RuntimeException e) {
            String msg = e.getMessage();
            if (msg.contains("ORA-00001")) {
                throw new RuntimeException("存在同个定损报价单, 请检查数据!!");
            }else {
                throw new RuntimeException(e);
            }
        }
        updateCarEvaluation(lossQuotation);
//        if ("dividendApprove".equals(lossQuotation.getState()))lossQuotation.setWrite(false);
        return  (LossQuotation) insertCommonData(lossQuotation);
    }


    public String getGetCarType(Model model) {
        String getCarType = "";
        if (model instanceof LossQuotation){
            LossQuotation lossQuotation = (LossQuotation) model;
            if (Objects.nonNull(lossQuotation.getTypeBusinesses()) && lossQuotation.getTypeBusinesses().size() > 0) {
                getCarType = lossQuotation.getTypeBusinesses().stream().map(item -> item.getPickUpType().getDescription())
                        .collect(Collectors.joining(","));
            }
        }else if (model instanceof ServicePlan){
            ServicePlan servicePlan = (ServicePlan) model;
            if (Objects.nonNull(servicePlan.getPickUpTypeS()) && (servicePlan.getPickUpTypeS().size() > 0)) {
                getCarType = servicePlan.getPickUpTypeS().stream()
                        .map(item ->  item.getPickUpType().getDescription()).collect(Collectors.joining(","));
            }
        }

        return getCarType;
    }

    private void checkDividendApprove(LossQuotation lossQuotation, SimpleRequest request) {
        String id = lossQuotation.getId();
        StringBuffer sf = new StringBuffer();
        LossQuotation old = lossQuotationRepository.findOne(id);
        old.getLossQuotationPlans().forEach(lossQuotationPlan -> {
            lossQuotation.getLossQuotationPlans().forEach(newPlan -> {
                if (newPlan.getId().equals(lossQuotationPlan.getId())&&newPlan.getDividendStore()!=lossQuotationPlan.getDividendStore()) {
                    lossQuotation.setState("dividendApprove");
                    sf.append("商品编码:"+newPlan.getProduct().getId()+",新分成率:"+newPlan.getDividendStore()+",旧分成率:"+lossQuotationPlan.getDividendStore()+";\n");
                    newPlan.setDividendStoreOld(lossQuotationPlan.getDividendStore());
                }
            });
        });
        if ("dividendApprove".equals(lossQuotation.getState())){
            //记录下日志
            SpringManager.getBean(ApesLoggerService.class).sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", lossQuotation.getInnerBusinessType(),
                    "businessKey", lossQuotation.getId(), "operate", "修改分成率",
                    "remark",sf.toString(),
                    "workPostName",request.getSession() != null ? request.getSession().getAttribute("workPostName", String.class) : null,
                    "operator_id", ((User)request.getCurrentUser()).getId()));
        }
    }

    /**
     * 分成审核
     * @return
     */
    public LossQuotation dividendApprove(SimpleRequest request){
        checkData(request);
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        lossQuotation.setState("confirmPlan");
        AtomicReference<Double> total = new AtomicReference<>(0.0);
        lossQuotation.getLossQuotationPlans().forEach(lossQuotationPlan -> {
            lossQuotationPlan.setDividendStoreOld(lossQuotationPlan.getDividendStore());
            total.updateAndGet(v -> v + (lossQuotationPlan.getDividendStore()*lossQuotationPlan.getFixedLossAmount()));
        });
        double v = total.get() / lossQuotation.getInsuranceOffer();
        lossQuotation.setDividendStore(Arith.round(v,2));
        lossQuotation.setDividendBase(Arith.round(1-v-lossQuotation.getDividendPlatform(),2));
        lossQuotation.computeAmount();
        SpringManager.getBean(TodoTaskService.class).finishTask(lossQuotation);

        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }

    /**
     * 分成审核退回
     * @return
     */
    public LossQuotation dividendBack(SimpleRequest request){
        checkData(request);
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        lossQuotation.setState("confirmPlan");
        lossQuotation.getLossQuotationPlans().forEach(lossQuotationPlan -> {
            lossQuotationPlan.setDividendStore(lossQuotationPlan.getDividendStoreOld());
        });
        SpringManager.getBean(TodoTaskService.class).finishTask(lossQuotation);
        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }
    public String repeal (SimpleRequest request) throws Exception {
        checkData(request);
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        //判断定损单是否还有 未完成的要货, 服务,
        List<ProductRequire> productRequires =
                lossQuotationRepository.findProductRequireForID(lossQuotation.getId());
        List<LossQuotationItem> lossQuotationItems = lossQuotationRepository.findLossQuotationItemForID(lossQuotation.getId());
        if (productRequires.size() > 0 || lossQuotationItems.size() >0)
            throw new RuntimeException("该定损单已经存在未完成的要货,服务方案.不能终止!!!");
        updateCarAccident(lossQuotation,2);
        lossQuotation.setRepealUid(getPerson(request));//设置人员
        lossQuotation.setRepealDate(new Date());
        lossQuotation.setState("repeal");
        lossQuotationRepository.saveAndFlush(lossQuotation);
        servicePlanceService.submitSynGYSXJD(lossQuotation.getId());
        return "终止成功！";
    }


    /**
     * 检查数据
     * @param request
     * @return
     */
    private void checkData(SimpleRequest request) {
        String id = request.get("id");
        int versions = request.get("version"); // 获取当前请求的版本信息
        LossQuotation lossQuotation = lossQuotationRepository.findOne(id);
        if (lossQuotation == null) throw new RuntimeException("定损报价单【" + id + "】在系统中不存在。");
        if ("approve".equals(lossQuotation.getState()) || "toInquiry".equals(lossQuotation.getState())) throw new RuntimeException("定损报价单已经已生成其他单据,请勿再操作!!!");
        if (lossQuotation.getVersion() != versions) throw new RuntimeException("记录已更新或已删除，请重新提交！");
        JSONArray lossQuotationPlans1 = request.getJO().getJSONArray("lossQuotationPlans");
        JSONArray lossQuotationItems = request.getJO().getJSONArray("lossQuotationItems");
        checkItemData(lossQuotationPlans1, lossQuotation.getLossQuotationPlans());
        checkItemData(lossQuotationItems, lossQuotation.getLossQuotationItems());
        if (request.get("state").equals("confirmPlan")){
            JSONObject jo = request.getJO();
            JSONArray lossQuotationPlans = jo.getJSONArray("lossQuotationPlans");
            lossQuotationPlans.stream()
                    .map(o -> ((JSONObject)o))
                    .filter(lossQuotationPlan -> lossQuotationPlan.getBoolean("done"))
                    .forEach(lossQuotationPlan -> {
                        lossQuotation.getLossQuotationPlans().forEach(lossQuotationPlan1 -> {
                            if (lossQuotationPlan1.getId().equals(lossQuotationPlan.getString("id"))) {
                                if (lossQuotationPlan1.getFixedLossPrice()!=lossQuotationPlan.getDoubleValue("fixedLossPrice"))
                                    throw new RuntimeException("商品:"+lossQuotationPlan1.getProduct().getName()+"定损单价不可修改");
                            }
                        });
                    });
        }
    }

    private void checkItemData(JSONArray lossQuotationPlans1, List quotationPlans) {
        Map<String, List<JSONObject>> stringListMap = lossQuotationPlans1.stream().map(o -> (JSONObject) o)
                .filter(jsonObject -> jsonObject.get("id")!=null)
                .collect(groupingBy(jsonObject -> jsonObject.getString("id")));
        quotationPlans.stream().forEach(lossQuotationPlan -> {
            Model quotationPlan = (Model) lossQuotationPlan;
            List<JSONObject> jsonObjects = stringListMap.get(quotationPlan.getInnerBusinessKey());
            if (jsonObjects==null||jsonObjects.isEmpty()){
               return;
            }
            JSONObject plansJ = jsonObjects.get(0);
            if (quotationPlan.getVersion()!=plansJ.getInteger("version"))
                throw new RuntimeException("记录已更新或已删除，请重新提交！");
        });
    }

    /**
     * 检查是否存在相同商品
     * @param
     * @return
     */
    private void checkGoods(List<LossQuotationItem> lossQuotationItem) {
        JSONObject flag = new JSONObject();
        lossQuotationItem.forEach(
                item -> {
                    if (ServicePlanceService.PLATFORM_OUT_ORDER.contains(item.getProduct().getBrand().getName()))
                        throw new RuntimeException(item.getProduct().getName()+" 商品属于定制款商品,请前往黑盒商城下单! !");
                    String product = item.getProduct().getId();
                    if (flag.getBooleanValue(product)) {
                        throw new RuntimeException("商品编码:"+product+"已经存在,请勿重复添加!!!");
                    }else {
                        flag.put(product,true);
                    }
                }
        );
    }


    /***
     * 根据基地或者门店查询车险报案单
     */
    public Page<Object[]> findCarAccidentByDeptOrBase(SimpleRequest request){
        JSONObject param = parseCondition(request);
        //首先判断该车牌是否存在有效的门店接车单
        if (param.containsKey("CAR_NUMBER")) {
            Enumeration pickCarType =  SpringManager.getBean(EnumerationRepository.class).findOne("pickA");
            List<PickUpCar> list =  SpringManager.getBean(PickUpCarRepository.class).findAll(
                    JpaDsl.toCriteriaByEq("licenseNumber",param.getString("CAR_NUMBER"),
                            "state","approve","pickCarType",pickCarType)
            );
            if (list != null && list.size() == 0) throw new RuntimeException("该车牌还没接车,请先用黑盒接车!!!");
        }
        JSONArray array = lossQuotationDao.findCarAccidentByDeptOrBase(param);
        if (array.size() ==0) throw new RuntimeException("请检查该车是否已填写评估信息,是否是转基地定损,是否已经黑盒接车, 是否已做内协交车单!!!!");
        Pageable pageable = PageRequest.of(request.get("page"), request.get("size"));
        int fromIndex = pageable.getPageSize()*pageable.getPageNumber();
        int toIndex = pageable.getPageSize()*(pageable.getPageNumber()+1);
        if(toIndex > array.size()) toIndex = array.size();
        JSONArray current = new JSONArray(array.subList(fromIndex,toIndex));
        PageImpl page = new PageImpl<>(current, pageable, array.size());
        return page;
    }

    /**
     * 转技术审核
     *
     * @param request
     * @return
     */
    public LossQuotation toTechAudit(SimpleRequest request){
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        checkCarInformation(lossQuotation.getCustomerExpand());
        if (!judgeToTechnical(lossQuotation)) throw new RuntimeException("该定损报价单无需转技术审核!!!!!!") ;
        lossQuotation.setState("toTechAudit");
        setInformationDetail(request,lossQuotation);
        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }

    /**
     * 技术审核
     *
     * @param request
     * @return
     */
    public LossQuotation techAudit(SimpleRequest request){
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        lossQuotation.setState("techAudit");
        setInformationDetail(request,lossQuotation);

        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }

    /**
     * 转技术审核拒绝-更新状态
     * @param request
     * @return
     */
    public LossQuotation techAuditRefuse (SimpleRequest request){
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        lossQuotation.setState("create");
        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }


    /**
     * 转询价
     *
     * @param request
     * @return
     */
    public LossQuotation toInquiry(SimpleRequest request){
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        //判断商品是否需要图片
        checkProductPic(lossQuotation);
        LossQuotation quotation = lossQuotationRepository.findOne(lossQuotation.getId());
        String operate = toInquiry_main(request,lossQuotation,"toInquiry");
        switch (operate){
            case  "toInquiry":
//                lossQuotation.setState("toInquiry");
//                getBean(FnEnquiryService.class).turnEnquiry(request);//供应商平台询价
                break;
            case "inquiryFinish":
//                lossQuotation.setState(oldState);
                break;
            case "notInquiry":
                throw new RuntimeException("无需询价");
            default:
                throw new RuntimeException("发生内部错误");
        }
        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }


    /**
     * 判断商品是否需要图片
     * @param lossQuotation
     */
    public void checkProductPic(LossQuotation lossQuotation){
        List<LossQuotationItem> needPicture = lossQuotation.getLossQuotationItems().stream().filter(lossQuotationItem -> lossQuotationItem.getProduct().getInquiryValid()).collect(Collectors.toList());
        if (needPicture.size()>0){
            StringBuffer sf = new StringBuffer();
            sf.append("转询价失败,以下配件需要上传图片");
            List<LossQuotationItem> noFile = needPicture.stream().filter(lossQuotationItem -> {
                JSONArray mapAddress = JSONObject.parseArray(lossQuotationItem.getMapAddress());
                if (mapAddress==null||mapAddress.size()==0){
                    sf.append(", ["+lossQuotationItem.getProduct().getId()+"]"+lossQuotationItem.getProduct().getName());
                }
                return mapAddress==null||mapAddress.size()==0;
            }).collect(Collectors.toList());
            if (noFile.size()>0)throw new RuntimeException(sf.toString());
        }
    }
    /**
     * 判断是否询价    *
     * @param
     * @return
     */
    public void judgmentInquiry(LossQuotation lossQuotation){

        List<LossQuotationItem> lossQuotationItems = lossQuotation.getLossQuotationItems();

        List<LossQuotationItem> needInquiry = lossQuotationItems.stream().filter(lossQuotationItem -> lossQuotationItem.getFixedLossPrice() < 0).collect(toList());

        if (needInquiry.size()>0)throw new RuntimeException("存在定损单价为零的商品:"+needInquiry.get(0).getProduct().getName());

        Map inquiryPool = this.invoke("commodityInquiry.order.getInquiryPool",new JSONObject(MapUtil.mapped(lossQuotation,"lossQuotationItems","lossQuotationPlans")) );

        List<LossQuotationItem> needCheckItems = lossQuotationItems
                .stream()
                .filter(lossQuotationItem ->
                    //过滤出需要询价的商品
                    lossQuotationItem.isProductRule() || lossQuotationItem.getProduct().getProductGroup().getId().equals("10") || lossQuotationItem.getUniqueValue() != null ||lossQuotationItem.getPriceForward()!=null
                ).filter(lossQuotationItem -> {
                    //过滤出库存不足的商品
                    JSONObject json = new JSONObject();
                    json.put("deptId", lossQuotation.getFixedLossDept().getId());
                    json.put("productId", lossQuotationItem.getProduct().getId());
                    double planKys = servicePlanDao.queryLocalStore(json);
                    return planKys < lossQuotationItem.getSaleQty();
                }).collect(Collectors.toList());

        for (LossQuotationItem lossQuotationItem : needCheckItems) {
            //生成服务单为确认状态不需要判断
            if (lossQuotationItem.getServicePlan() != null && servicePlanRepository.findOne(lossQuotationItem.getServicePlan()).getConfirmDate() != null)
                continue;
            //新平台询价
            if (checkNewPlatformInquiry(lossQuotationItem))
                continue;
            //判断外采询价
            if (checkExternalInquiry(lossQuotationItem))
                continue;
            //老系统询价
            if (lossQuotationItem.getUniqueValue() != null)
                checkOldSystemInquiry(inquiryPool, lossQuotationItem);
        }
    }

    private boolean checkExternalInquiry(LossQuotationItem lossQuotationItem) {
        if (!lossQuotationItem.checkExternalInquiry()) return false;
        boolean invoke = invoke("scm.externalInquiryService.sourceConfirmPriceValid", mapper("id", lossQuotationItem.getOldInquiryNumber(), "unique", lossQuotationItem.getUniqueValue()));
        if (!invoke)throw new RuntimeException("存在询价过期商品:"+lossQuotationItem.getProduct().getName());
        return true;
    }

    private void checkOldSystemInquiry(Map inquiryPool, LossQuotationItem lossQuotationItem) {
        boolean outFlag;
        outFlag=false;
        for ( Object item : (List) inquiryPool.get("item")) {
            JSONObject sourceProduct = new JSONObject((Map) item);
            for (Object o : sourceProduct.getJSONArray("item")) {
                JSONObject inquiryProduct = new JSONObject((Map) o);
                if (inquiryProduct.getString("WYZ").equals(lossQuotationItem.getUniqueValue())){
                    outFlag=true;
                }
            }
        }
        if (!outFlag){
            throw new RuntimeException("存在询价过期商品,请重新询价:"+lossQuotationItem.getProduct().getName());
        }
    }

    private boolean checkNewPlatformInquiry(LossQuotationItem lossQuotationItem) {
        if (Objects.nonNull(lossQuotationItem.getPriceForward()) && "1-4".contains(lossQuotationItem.getPriceForward()))//价格前置商品
            return true;
        if("2".equals(lossQuotationItem.getPriceForward())){ //新平台询价
            JSONObject result =  JSON.parseObject(invoke("sp.enquiryService.findByID", MapUtil.mapper("id",lossQuotationItem.getOldInquiryNumber())));
            JSONObject body = result.getJSONObject("body");
            JSONObject  isState =  JSON.parseObject(invoke("sp.enquiryService.findQuoteResultState",MapUtil.mapper("id",lossQuotationItem.getUniqueValue())));
            boolean state = isState.getBoolean("body");

            if(body!=null && new Date().getTime()<body.getDate("quoteExpireDate").getTime() && state) return true;
            throw new RuntimeException("存在询价过期商品:"+lossQuotationItem.getProduct().getName());
        }
        //巴图鲁询价
        if ("5".equals(lossQuotationItem.getPriceForward())){
            //获取巴图鲁询价过期时间
            JSONObject  result =  JSON.parseObject(invoke("sp.quoteResult.findOne",MapUtil.mapper("id",lossQuotationItem.getQuoteResultId())));
            JSONObject body = result.getJSONObject("body");
            if(body!=null && new Date().getTime()<body.getDate("expiredTime").getTime() && body.getString("state") != "20") return true;
            throw new RuntimeException("存在询价过期商品:"+lossQuotationItem.getProduct().getName());
        }
        return false;
    }

    /**
     * 申请定损协助    *
     * @param
     * @return
     */
    public Map  applyHelp(SimpleRequest simpleRequest){
        LossQuotation lossQuotation = simpleRequest.getO(LossQuotation.class);
        Dept assistBase = lossQuotation.getAssistBase();
        if (Objects.isNull(assistBase)){
            throw new RuntimeException("申请定损协助,协助定损基地不能为空,请选择协助定损基地!!!");
        }
        // 5013 1002  志运基地 和如约基地不能 选择
        InsuranceRule insuranceRule = SpringManager.getBean(InsuranceRuleRepository.class)
                .findAll(JpaDsl.toCriteria(MapUtil.mapper("insuranceCompany.id", lossQuotation.getInsuranceCompany().getId(), "company.id", assistBase.getCompany().getId())))
                .stream().findFirst().orElseThrow( () -> new RuntimeException("该基地无权限开发票,请从新选择基地!!!") );
        if (Objects.equals("5013",assistBase.getCompany().getId()) || Objects.equals("1002",assistBase.getCompany().getId())){
            lossQuotation.setAssistBaseID(lossQuotation.getAssistBase().getBranch().getId());
        }
        lossQuotation = lossQuotationRepository.saveAndFlush(lossQuotation);
        return MapUtil.mapped(lossQuotation);
    }

    /**
     * 转商务审核
     *
     * @param request
     * @return
     */
    public Map toBusinessAudit(SimpleRequest request){
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        lossQuotation.setApplyApprove(SpringManager.getBean(BusinessAttributeValueRepository.class).findOne("LossQuotation.applyApprove.A"));
        //判断是否能转价格申请
        toBusinessAuditException(lossQuotation);
        LossQuotation quotation = lossQuotationRepository.findOne(lossQuotation.getId());
        String state = quotation.getState();
        judgmentInquiry(lossQuotation);
        // 判断商品有价格的是否有库存
        checkProductStore(lossQuotation);
        //判断申请审核事项，不同得审核对应得逻辑不一样
        if (!"confirmPlan".equals(state)) {
            throw new RuntimeException("价格申请,必须先确认方案!!!");
        } else {
            List<LossQuotationPlan> list = lossQuotation.getLossQuotationPlans().stream().filter(
                    item -> item.getFixedLossPrice() == 0
            ).collect(toList());
            List<LossQuotationPlan> payYour = lossQuotation.getLossQuotationPlans().stream().filter(
                    item -> !item.isPayYourself()
            ).collect(toList());
            if (list.size() > 0) throw new RuntimeException("确认方案明细的定损单价不能为零!!!");
            if (payYour.size() ==0) throw new RuntimeException("确认方案明细不能全是转自费商品!!!");
        }
        lossQuotation.setState("toBusinessAudit");
        if (lossQuotation.getLossQuotationPlans().size() == 0 ){
            throw new RuntimeException("转商务审核,确认方案没有数据!!!");
        }
        setInformationDetail(request,lossQuotation);
        if (lossQuotation.getNeedBusinessAudit())addLossQuotationLogger(lossQuotation,"发起oa审核","",request);
        lossQuotation = lossQuotationRepository.saveAndFlush(lossQuotation);
        return MapUtil.mapped(lossQuotation);
    }

    /**
     * 要货审核
     * @param request
     * @return
     */
    public Map advanceTakeGoodsAudit(SimpleRequest request){
        JSONObject jo = request.getJO();
        LossQuotation lossQuotation = lossQuotationRepository.findOne(jo.getString("id"));
        lossQuotation.setApplyApprove(SpringManager.getBean(BusinessAttributeValueRepository.class).findOne("LossQuotation.applyApprove.B"));
        // 判断商品是否有库存
        checkProductStore(lossQuotation);
        //判断询价商品是否过期
        timeoutEnquiry(lossQuotation);
        //将用户输入数据写入定损单
        writeUserInputTakeGoodsData(jo, lossQuotation);
        checkTakeGoodsAudit(lossQuotation);

        //验证要货的时候，是否能够要货
        checkShutDownProduct(lossQuotation);
        lossQuotation.setState("turnRequireProduct");
        setInformationDetail(request,lossQuotation);
        if (lossQuotation.getNeedBusinessAudit())addLossQuotationLogger(lossQuotation,"发起要货审核","",request);
        lossQuotation = lossQuotationRepository.saveAndFlush(lossQuotation);
        return MapUtil.mapped(lossQuotation);
    }

    /**
     * 判断询价商品是否过期
     * @param lossQuotation
     */
    private void timeoutEnquiry(LossQuotation lossQuotation){
        for (LossQuotationItem lossQuotationItem : lossQuotation.getLossQuotationItems()) {
            JSONObject json = new JSONObject();
            json.put("deptId", lossQuotation.getFixedLossDept().getId());
            json.put("productId", lossQuotationItem.getProduct().getId());
            double planKys = servicePlanDao.queryLocalStore(json);
            if (Objects.nonNull(lossQuotationItem.getPriceForward()) && "1-4".contains(lossQuotationItem.getPriceForward()))continue;//价格前置商品
            if ("2".equals(lossQuotationItem.getPriceForward())) { //新平台询价
                JSONObject result = JSON.parseObject(invoke("sp.enquiryService.findByID", MapUtil.mapper("id", lossQuotationItem.getOldInquiryNumber())));
                JSONObject body = result.getJSONObject("body");
                JSONObject isState = JSON.parseObject(invoke("sp.enquiryService.findQuoteResultState", MapUtil.mapper("id", lossQuotationItem.getUniqueValue())));
                boolean state = isState.getBoolean("body");

                if (body != null && new Date().getTime() < body.getDate("quoteExpireDate").getTime() && state) continue;
                if (planKys>=lossQuotationItem.getSaleQty())continue;
                throw new RuntimeException("存在询价过期商品:" + lossQuotationItem.getProduct().getName());
            }
            //巴图鲁询价
            if ("5".equals(lossQuotationItem.getPriceForward())){
                //获取巴图鲁询价过期时间
                JSONObject  result =  JSON.parseObject(invoke("sp.quoteResult.findOne",MapUtil.mapper("id",lossQuotationItem.getQuoteResultId())));
                JSONObject body = result.getJSONObject("body");
                if(body!=null && new Date().getTime()<body.getDate("expiredTime").getTime() && body.getString("state") != "20") continue;
                if (planKys>=lossQuotationItem.getSaleQty())continue;
                throw new RuntimeException("存在询价过期商品:"+lossQuotationItem.getProduct().getName());
            }
        }
    }

    private void checkTakeGoodsAudit(LossQuotation lossQuotation) {
        List<LossQuotationItem> list = lossQuotation.getLossQuotationItems().stream().filter(
                item ->  item.getRequireQty() >0
        ).collect(toList());
        if (list.size() == 0) throw new RuntimeException("要货申请,必须填写要货数量!!!");
        list = list.stream().filter(
                item ->  item.getSalePrice() == 0 || item.getMinimumPrice() ==0
        ).collect(toList());
        if (list.size() >0)
            throw new RuntimeException("要货商品:"+list.get(0).getProduct().getId()+"价格不能为零,请先转询价!!!");
        list = getSoldOutGoods(lossQuotation);
        //判断无货商品是否有要货
        list.stream().filter(item -> item.getRequireQty() > 0).forEach(item -> {
            throw new RuntimeException("要货商品存在无货商品!!!编码:" + item.getProduct().getId());
        });
    }

    private void writeUserInputTakeGoodsData(JSONObject jo, LossQuotation lossQuotation) {
        JSONArray auditItems = jo.getJSONArray("lossQuotationItems");
        Map<String,Integer> requireQtyMap = new HashMap();
        auditItems.stream()
                .forEach(o -> {
                    JSONObject jsonObject = (JSONObject) o;
                    if (jsonObject.getBoolean("selected"))
                        requireQtyMap.put(jsonObject.getString("productId"),jsonObject.getInteger("requireQty"));
                });
        lossQuotation.getLossQuotationItems().stream()

                .forEach(item ->{
                    String id = item.getProduct().getId();
                    if (requireQtyMap.containsKey(id)) item.setRequireQty(requireQtyMap.get(id));
                });
    }

    /**
     * 提前修车审核
     * @param request
     * @return
     */
    public Map advanceFixAudit(SimpleRequest request){
        JSONObject jo = request.getJO();
        LossQuotation lossQuotation = lossQuotationRepository.findOne(jo.getString("id"));
        lossQuotation.setApplyApprove(SpringManager.getBean(BusinessAttributeValueRepository.class).findOne("LossQuotation.applyApprove.C"));
        JSONArray auditItems = jo.getJSONArray("lossQuotationItems");
        List<LossQuotationItem> lossQuotationItems = lossQuotation.getLossQuotationItems();
        //获取勾选的商品
        List<String> stringList = auditItems.stream()
                .filter(o -> ((JSONObject) o).getBoolean("selected"))
                .map(o -> ((JSONObject) o).getString("productId"))
                .collect(toList());
        lossQuotationItems.stream().filter(item ->StringUtils.isEmpty(item.getServicePlan())).forEach(lossQuotationItem -> lossQuotationItem.setAdvanceRepair(false));
        lossQuotationItems.stream()
                .filter(lossQuotationItem -> stringList.contains(lossQuotationItem.getProduct().getId()))
                .forEach(lossQuotationItem -> lossQuotationItem.setAdvanceRepair(true));

        List<LossQuotationItem> list = getAdvanceRepairGoods(lossQuotation);
        if (list.size() == 0) {
            throw new RuntimeException("定损明细没有提前修车商品,请检查!!!");
        }
        list = getNotPriceGoods(lossQuotation);
        if (list.size() > 0) {
            throw new RuntimeException("存在价格为零的商品");
        }
        list = getSoldOutGoods(lossQuotation);
        // 判断商品是否有库存
        checkProductStore(lossQuotation);
        //判断无货商品是否有提前修车得
        list.stream().filter(LossQuotationItem::isAdvanceRepair).forEach(item -> {
            throw new RuntimeException("提前修车商品存在无货商品,编码:" + item.getProduct().getId());
        });
        lossQuotation.setState("turnRepairApprove");

        setInformationDetail(request,lossQuotation);

        if (lossQuotation.getNeedBusinessAudit())addLossQuotationLogger(lossQuotation,"发起提前修车审核","",request);

        lossQuotation = lossQuotationRepository.saveAndFlush(lossQuotation);

        return MapUtil.mapped(lossQuotation);
    }

    /**
     * 获取审核商品
     * @param request
     * @return
     */
    public JSONObject auditItems(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONObject result = jo;
        LossQuotation lossQuotation = lossQuotationRepository.findOne(jo.getString("id"));
        String auditType = jo.getString("auditType");
        List<Map> items = null;
        if ("advanceFix".equals(auditType)){
            items = lossQuotation.getLossQuotationItems().stream()
                    //               是否生成方案                                     价格为零的商品
                    .filter(item -> item.getServicePlan() == null && !item.isPlan()&&item.getSalePrice()!=0)
                    //判断无货商品
                    .filter(LossQuotationItem::isAgree)
                    .map(lossQuotationItem -> {
                        Product product = lossQuotationItem.getProduct();
                        ServeType serveType = product.getServeType();
                        return mapper("categoryName", product.getCategory().getName(),
                                "product", "[" + product.getId() + "]" + product.getName(),
                                "productId", product.getId(),
                                "serveType", "[" + serveType.getId() + "]" + serveType.getName(),
                                "qty", lossQuotationItem.getSaleQty(),
                                "saleAmount", lossQuotationItem.getSalePrice(),
                                "totalAmount", lossQuotationItem.getSalesAmount()
                        );
                    }).collect(toList());
        }else if("advanceTakeGoods".equals(auditType)){
            items = lossQuotation.getLossQuotationItems().stream()
                    //无价格
                    .filter(item -> item.getSalePrice() != 0 && item.getMinimumPrice() !=0
                            &&!item.isProductRule() && item.isAgree() && "10".equals(item.getProduct().getProductGroup().getId()))
                    .map(lossQuotationItem -> {
                        Product product = lossQuotationItem.getProduct();
                        ServeType serveType = product.getServeType();
                        return mapper("categoryName", product.getCategory().getName(),
                                "product", "[" + product.getId() + "]" + product.getName(),
                                "productId", product.getId(),
                                "serveType", "[" + serveType.getId() + "]" + serveType.getName(),
                                "inquiryGooodsState", lossQuotationItem.getInquiryGooodsState(),
                                "oldInquiryNumber", lossQuotationItem.getOldInquiryNumber(),
                                "receiveQty", lossQuotationItem.getReceiveQty(),
                                "requireQty", lossQuotationItem.getRequireQty(),
                                "qty", lossQuotationItem.getSaleQty(),
                                "saleAmount", lossQuotationItem.getSalePrice(),
                                "referTax", lossQuotationItem.getReferTax()
                        );
                    }).collect(toList());
        }else {
            throw new RuntimeException("错误类型:"+auditType);
        }

        result.put("lossQuotationItems",items);
        return result;
    }

    public void addLossQuotationLogger(LossQuotation lossQuotation,String operate,String remark,SimpleRequest request){
        PartyRole person = request.getPerson();
        User user = null;
        if (person!=null){
            user =SpringManager.getBean(UserRepository.class).findAll(JpaDsl.toCriteriaByEq("person.id",person.getId())).stream().findFirst().orElse(null);
        }
        addLossQuotationLogger(lossQuotation,operate,remark,user);
    }

    public void addLossQuotationLogger(Model model, String operate, String remark, User user){
        if (user==null){
            addLossQuotationLogger(model,operate,remark);
        }else {
            addLossQuotationLogger(model,operate,remark,user.getId());
        }

    }

    public void addLossQuotationLogger(Model model,String operate,String remark,Integer UID){
        apesLoggerService.sendSynEvent("event:ir.logger.create",
                MapUtil.mapper(
                        "businessType", model.getInnerBusinessType(),
                        "businessKey", model.getInnerBusinessKey(),
                        "operate", operate,
                        "workPostName",null,
                        "remark",remark,
                        "operator_id", UID)
        );
    }
    public void addLossQuotationLogger(Model model,String operate,String remark){
        apesLoggerService.sendSynEvent("event:ir.logger.create",
                MapUtil.mapper(
                        "businessType", model.getInnerBusinessType(),
                        "businessKey", model.getInnerBusinessKey(),
                        "operate", operate,
                        "workPostName",null,
                        "remark",remark)
        );
    }

    private void toBusinessAuditException(LossQuotation lossQuotation) {
//        if (judgeToTechnical(lossQuotation) && lossQuotation.getTechDate() == null)
//            throw new RuntimeException("有需要技术审核的商品, 请先转技术审核!!!!");
//        if (StringUtils.isEmpty(lossQuotation.getApplyApprove()))
//            throw new RuntimeException("转商务审核必选选择申请审核事项!!!");
//        String apply = lossQuotation.getApplyApprove().getName();
        if (StringUtils.isEmpty(lossQuotation.getAccidentPhotos()))
            throw new RuntimeException("未上传定损清单，请在页签“案件资料”上传定损清单后，再转审核。");

    }

    public LossQuotation businessAuditLog(SimpleRequest request){
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        addLossQuotationLogger(lossQuotation,"自动审核","",request);
        return lossQuotation;
    }

    /**
     * 商务审核
     *
     * @param request
     * @return
     */
    public LossQuotation businessAudit(SimpleRequest request){
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        String apply = lossQuotation.getApplyApprove().getName();
        switch (apply) {
            case "价格申请":
                lossQuotation.setState("businessAudit");
                setInformationDetail(request,lossQuotation);
                //需要先更新定损单状态,因为推送服务方案到app需要用到
                lossQuotation = lossQuotationRepository.saveAndFlush(lossQuotation);
                insertServicePlan(lossQuotation,apply);     // 回写服务方案价格也走这里
                break;
            case "要货申请":
                divideItems(lossQuotation,request);
                updateReceivedQty(lossQuotation);
                lossQuotation.setState("create");
//                lossQuotation.setState("techAudit");
                break;
            case "提前修车申请":
                //更新服务单号,到具体明细商品上去
                insertServicePlan(lossQuotation,apply);
                lossQuotation.setState("create");
//                lossQuotation.setState("techAudit");
                break;
            default: throw new RuntimeException("出现未匹配申请事项，该操作无效!!!!");

        }
        //异步回写预估
        JSONObject object = new JSONObject();
        object.put("id", lossQuotation.getId());
        outboxSubscriberService.commonSendRequest("local:LossQuotation.writeEstimatedCommission", "Fixed" + lossQuotation.getId(), object);

        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }

    /**
     * 生成服务单
     * @param lossQuotation
     */
    private void insertServicePlan(LossQuotation lossQuotation,String apply) {
        //apply apply 区分 提前修车和正常修车
        if (!"提前修车申请".equals(apply)) {
            //回写服务方案单定损金额
            updateServicePlanMoney(lossQuotation);
            List<LossQuotationPlan> lossQuotationPlans = getLossQuotationPlans(lossQuotation);  // 获取不是自费并且服务单号为空的确认方案
            if (lossQuotationPlans.size() == 0) return;     // 这里会返回
            // List<LossQuotationPlan> payYourSelf = getPayYourSelf(lossQuotation) ;
            // if (payYourSelf.size() > 0) return;
        }
        String servicePlan = packageDataToService(lossQuotation);
        updatePlanIdForDetail(lossQuotation, servicePlan);
    }

    /**
     * 结束OA并刷新数据
     * @param request
     * @return
     */
    public LossQuotation endOAAndRefresh(SimpleRequest request) {
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        lossQuotation.setState("businessAudit");
        setInformationDetail(request,lossQuotation);
        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }

    /**
     * 获取不是自费并且服务单号为空的确认方案
     * @param lossQuotation
     * @return
     */
    private List<LossQuotationPlan> getLossQuotationPlans(LossQuotation lossQuotation) {
        return lossQuotation.getLossQuotationPlans().stream().filter(
                item -> !item.isPayYourself() && StringUtils.isEmpty(item.getServicePlan())
        ).collect(toList());
    }
    /**
     * 检查数量为零得商品
     * @param lossQuotation
     * @return
     */
    private void checkGoodsWithZeroQty(LossQuotation lossQuotation) {
        lossQuotation.getLossQuotationItems().forEach(
                item -> {
                    if (Objects.equals("工时",item.getCategory().getName()) && item.getRequireQty() >0)
                        throw new RuntimeException("工时商品不能要货!!!商品:" + item.getProduct().getId());
                }
        );
        List<LossQuotationItem> list =  lossQuotation.getLossQuotationItems().stream().filter(
                item -> item.getSaleQty() <= 0
        ).collect(toList());
        if ( list.size()>0){
            String str = list.stream().map( item -> item.getProduct().getId()).collect(Collectors.joining("/"));
            throw new RuntimeException(str + "等商品销售数量不能小于等于零!!!");
        }
    }

    /**
     * 获取自费商品
     * @param lossQuotation
     * @return
     */
    private List<LossQuotationPlan> getPayYourSelf(LossQuotation lossQuotation) {
        return lossQuotation.getLossQuotationPlans().stream().filter(
                item ->  item.isPayYourself() && StringUtils.isEmpty(item.getServicePlan())
        ).collect(toList());
    }
    /**
     * 确认方案
     * @param request
     * @return
     */
    public LossQuotation confirmPlan(SimpleRequest request){
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        // 判断商品是否有库存
        checkProductStore(lossQuotation);
        //确认方案,得判断是否已经技术审核, 是否有价格为零的商品
//        if (judgeToTechnical(lossQuotation) && lossQuotation.getTechDate() == null)
//            throw new RuntimeException("有需要技术审核的商品, 请先转技术审核!!!!");
        judgeGoodsPrice(lossQuotation);
        judgmentInquiry(lossQuotation);
        //将 定损明细商品,有服务标记的商品,转到确认方案上去
        boolean lossQuotationPlan = createLossQuotationPlan(lossQuotation);
        //判断状态是否为非确认方案 非确认方案时更改状态至确认方案
        if (lossQuotationPlan&&!lossQuotation.getState().equals("confirmPlan")){
            lossQuotation.setState("confirmPlan");
            return lossQuotationRepository.saveAndFlush(lossQuotation);
        }else if(lossQuotationPlan){
            throw new RuntimeException("转确认方案无具体商品,请检查!!!!");
        }
        lossQuotation.setState("confirmPlan");
        //设置申请审核事项为价格审核
        lossQuotation.setApplyApprove(
                SpringManager.getBean(BusinessAttributeValueRepository.class).findOne("LossQuotation.applyApprove.A")
        );
        setInformationDetail(request,lossQuotation);
        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }

    /**
     * 退回
     * 使单据退回到新增
     * @param request
     * @return
     */
    public LossQuotation goBack(SimpleRequest request){
        checkData(request);
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        handleLossQuotation(lossQuotation);
        lossQuotation.setPriceDifference(0);
        lossQuotation.setTotalAmount(0);
        lossQuotation.setInsuranceOffer(0);
        lossQuotation.setState("goBack");
        setInformationDetail(request,lossQuotation);
        lossQuotation.setState("create");
        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }

    /**
     *
     * 判断是否存在价格为零的商品
     * @param lossQuotation
     * @return
     */
    private void judgeGoodsPrice(LossQuotation lossQuotation){
        List<LossQuotationItem> list = lossQuotation.getLossQuotationItems()
                .stream().filter(
                        item -> {
                            return (item.getSalePrice() <= 0 || item.getMinimumPrice() <= 0) && item.isAgree();
                        }
                ).collect(toList());
        if (list.size() >0)
            throw new RuntimeException("页签'保险报价'得商品: "+list.get(0).getProduct().getId()+"最低定损单价为零, 请先转询价!!!");;
    }

    /**
     * 处理定损确认方案数据
     * @param lossQuotation
     */
    private void handleLossQuotation(LossQuotation lossQuotation) {
        List<LossQuotationPlan> lossQuotationPlan = lossQuotation.getLossQuotationPlans();
        if (lossQuotationPlan.size() > 0) {
            lossQuotation.getLossQuotationItems().forEach(
                    item -> {
                        if ((item.isPlan() && StringUtils.isEmpty(item.getServicePlan()))
                                || (item.isAdvanceRepair() && !StringUtils.isEmpty(item.getServicePlan()))){
                            item.setPlan(false);
                        }
                    }
            );
            lossQuotation.setLossQuotationPlans(
                    lossQuotationPlan.stream().filter(
                            item ->  !StringUtils.isEmpty(item.getServicePlan()) && item.isDone()
                    ).collect(toList())
            );
        }
    }

    //1.需要判断是否有库存无价格商品，提示：让采购定价格文件
    private void isNoPriceAndHaveStock(LossQuotation lossQuotation) {
        //TODO
    }

    /**
     * 设置相关信息
     * @param lossQuotation
     */
    private void setInformationDetail(SimpleRequest simpleRequest,LossQuotation lossQuotation){
        String state = lossQuotation.getState();
        switch (state){
            case "toTechAudit":
                lossQuotation.setToTechDate(new Date());
                lossQuotation.setToTechUid(getPerson(simpleRequest));
                break;
            case "techAudit":
                lossQuotation.setTechDate(new Date());
                lossQuotation.setTeachUid(getPerson(simpleRequest));
                break;
            case "toBusinessAudit":
                lossQuotation.setToBusinessDate(new Date());
                lossQuotation.setToBusinessUid(getPerson(simpleRequest));
                break;
            case "businessAudit":
                lossQuotation.setApproveDate(new Date());
                lossQuotation.setApproveUid(getPerson(simpleRequest));
                break;
            case "toInquiry":
                lossQuotation.setInquiryDate(new Date());
                lossQuotation.setInquiryUid(getPerson(simpleRequest));
                break;
            case "confirmPlan":
                lossQuotation.setConfirmDate(new Date());
                lossQuotation.setConfirmUid(getPerson(simpleRequest));
                break;
            case "goBack":
                lossQuotation.setBackDate(new Date());
                lossQuotation.setBackUid(getPerson(simpleRequest));
                break;
            case "repeal":
                lossQuotation.setRepealDate(new Date());
                lossQuotation.setRepealUid(getPerson(simpleRequest));
            default:
                break;
        }
    }
    /**
     * 设置转询价信息
     * @param lossQuotation
     */
    public void setToInquiryInfo(SimpleRequest simpleRequest,LossQuotation lossQuotation){
        lossQuotation.setInquiryDate(new Date());
        lossQuotation.setInquiryUid(getPerson(simpleRequest));
    }


    /***
     * 解析条件
     */
    private JSONObject parseCondition(SimpleRequest request) {
        JSONArray condition = request.getJO().getJSONArray("condition");
        JSONObject object = new JSONObject();
        condition.stream().forEach(json -> {
            JSONObject obj = (JSONObject) json;
            if (obj.get("value") != null) {
                if (obj.getString("type") == null) {
                    object.put(obj.getString("field"), obj.getString("value"));
                } else if (obj.getString("type").equals("date") && obj.getString("operator").equals("GTE")) {
                    object.put(obj.getString("field") + "_START", DateUtil.parse(obj.getString("value"), DateUtil.SHOW_DATETIME_FORMAT));
                } else if (obj.getString("type").equals("date") && obj.getString("operator").equals("LTE")) {
                    object.put(obj.getString("field") + "_END", DateUtil.parse(obj.getString("value"), DateUtil.SHOW_DATETIME_FORMAT));
                } else if (obj.getString("type").equals("date") && obj.getString("operator").equals("EQ")) {
                    object.put(obj.getString("field"), DateUtil.parse(obj.getString("value")));
                }
            }
        });
        try {
            Post post = postRepository.findOne(request.getPostId());
            object.put("DEPT",post.getDept().getId());
        } catch (Exception e) {
            throw new RuntimeException("当前操作员没有门店信息!!!");
        }
        return object;
    }

    /**
     * 转询价--main
     * operate  : toInquiry finishInquiry notInquiry
     *
     * @param simpleRequest
     * @return
     */
    public String toInquiry_main(SimpleRequest simpleRequest, LossQuotation lossQuotation,String state){
        String operate = "";
        //重取平台
        //转询价,首先判断该车是否停止服务车型
        FnCustomerExpand customerExpand = lossQuotation.getCustomerExpand();
        if (!StringUtils.isEmpty(customerExpand.getJekunModelCode())){
            CarConfiguration carConfiguration =
                    SpringManager.getBean(CarConfigurationRepository.class).getOne(customerExpand.getJekunModelCode());
            if("stopService".equals(carConfiguration.getValidFlag())) throw new RuntimeException("该车型已经停止服务,请联系后台人员维护!!!");
        }
        Map<String,List<LossQuotationItem>> map = this.getInquiryGoods(lossQuotation,new JSONArray(),new String()); //需要询价商品
        if(map.size() !=0){
            //createCommodityInquiry(lossQuotation,map,getPerson(simpleRequest)); //创建商品询价单
            operate  = "toInquiry";
        }else{
            operate  = "notInquiry";
        }
        return operate;
    }

    private JSONObject getInquiryInformation(SimpleRequest simpleRequest, LossQuotation lossQuotation) {
        Map toMap = simpleRequest.getMap();
        toMap.put("getCarDept", MapUtil.mapper("id",lossQuotation.getGetCarDept().getOrigin()));
        toMap.put("fixedLossDept",MapUtil.mapper("id",lossQuotation.getFixedLossDept().getOrigin()));
        //询价只需要判断未生成服务单.并且有同意标记得商品
        JSONArray  list  = ((JSONObject) toMap).getJSONArray("lossQuotationItems")
                .stream().filter(
                        item -> {
                            JSONObject tempJson = (JSONObject)item;
                            return tempJson.getBooleanValue("agree") && StringUtils.isEmpty(tempJson.getString("servicePlan"));
                        }).collect(Collectors.toCollection(JSONArray::new));
        if (list.size() == 0) throw new RuntimeException("无询价商品,请检查需询价商品是否有价格,是否已勾选同意标记!!!");
        list = list.stream().filter(lossQuotationItem ->{
            JSONObject tempJson = (JSONObject)lossQuotationItem;
            Boolean needInquiry = tempJson.getBoolean("needInquiry");//只有转询价入口的才会是false
            return needInquiry;
        }).collect(Collectors.toCollection(JSONArray::new));
        list.forEach((item)->{
            JSONObject tempJson = (JSONObject)item;
            tempJson.put("priceUnit",tempJson.getDoubleValue("salePrice"));
            lossQuotation.getLossQuotationItems().forEach((lossQuotationItem)->{
                Stock stock = SpringManager.getBean(StockRepository.class).findByProductAndLocation(lossQuotationItem.getProduct(),lossQuotationItem.getLocation());
                if(lossQuotationItem.getId().equals(tempJson.getString("id"))){
                    tempJson.put("product",MapUtil.mapper(
                            "id",lossQuotationItem.getProduct().getId(),
                            "name",lossQuotationItem.getProduct().getName(),
                            "orginID",lossQuotationItem.getProduct().getOrginID(),
                            "productGroup",MapUtil.mapped(lossQuotationItem.getProduct().getProductGroup()),
                            "brand",MapUtil.mapped(lossQuotationItem.getProduct().getBrand()),
                            "classify",MapUtil.mapped(lossQuotationItem.getProduct().getClassify())
                    ));
                    tempJson.put("MDKYS",stock == null ? 0 : stock.getMarketableQtyFaDs());
                }
            });
        });
        toMap.put("lossQuotationItems",list);
        toMap.put("inquirySource", "fixedLoss");
        //转换为老系统对应的公司编码
        ContrastPartyCode partyCode =
                SpringManager.getBean(ContrastPartyCodeRepository.class).findFirstByParty(lossQuotation.getCompany().getParty());
        toMap.put("XYGSID", partyCode.getGsid());
        toMap.put("GSID",partyCode.getGsid());
        toMap.put("FNVIPJBID", lossQuotation.getCustomerExpand().getCustomerLevelId());
        toMap.put("FNVIPSFID",lossQuotation.getCustomerExpand().getUserRoleId());
        JSONObject outerQueryJson = serviceToForeign.getInquiryDetail(toMap); //老框架获取回来数据
        return (JSONObject)(JSONObject.parse(outerQueryJson.getString("obj")));
    }


    /**
     * 创建商品询价单
     * @param
     */
    private void createCommodityInquiry( LossQuotation lossQuotation,Map<String,List<LossQuotationItem>> groupMap,PartyRole creator) {
        // 巴图鲁询价
        List<BusinessParam> findBaturuSupplier = SpringManager.getBean(BusinessParamRepository.class).findAllByQueryKey("baturuSupplier");
        String store = Objects.equals("B", lossQuotation.getOrderType().getCode())?lossQuotation.getGetCarDept().getId():lossQuotation.getFixedLossDept().getId();
        boolean isExistsPurGroup = judgeSendInquiryPurGroup(store, findBaturuSupplier.get(0).getValue3());

        CompanyEntry companyEntry = SpringManager.getBean(CompanyEntryRepository.class).findByPartyId(lossQuotation.getCompany().getParty().getId());
        boolean wantInvoiceFlag = ObjectUtils.isEmpty(companyEntry)?true:companyEntry.isWantInvoice();

        CarConfiguration carConfiguration = SpringManager.getBean(CarConfigurationRepository.class).findOne(lossQuotation.getCustomerExpand().getJekunModelCode());
        boolean scopeCarFlag = invoke("mdm.supplierBusinessScopeService.externalCallBusinessScopeCar", MapUtil.mapper("supplierId", findBaturuSupplier.get(0).getValue(), "carlabelId", carConfiguration.getCarLabel().getId()));

        JSONObject inquireData = new JSONObject();
        if (!wantInvoiceFlag && isExistsPurGroup && scopeCarFlag) this.baturuInquireMainData(lossQuotation, inquireData, checkCarInformation(lossQuotation.getCustomerExpand()));

        JSONArray array = new JSONArray();
        Dept fixedLossDept = "B".equals(lossQuotation.getOrderType().getCode())?lossQuotation.getGetCarDept():lossQuotation.getFixedLossDept();
        PartyRole platform = SpringManager.getBean(FnCommunalService.class).getPlatform(false, true, fixedLossDept);
        CommodityInquiryOrderService commodityInquiryOrderService = SpringManager.getBean(CommodityInquiryOrderService.class);
        groupMap.forEach((key,values)->{
            JSONObject data = new JSONObject();
            data.put("UNIQUE_ID", UUID.randomUUID().toString());
            data.put("DJLXID", "SX0");
            data.put("DJLXMC", "商品询价单");
            data.put("C_CDNM", "makeSPXJD");
            data.put("CPHM", lossQuotation.getCustomerExpand().getCarLicense());
            data.put("LYDJHM", lossQuotation.getInnerBusinessKey());
            data.put("LYDJLX", "lossQuotation");
            data.put("LYDJMC","定损报价单");
            LossQuotationItem lossQuotationItem = values.stream().findFirst().orElse(new LossQuotationItem());
            ServeType serveType = lossQuotationItem.getServeType();
            data.put("FWLXID", serveType.getId());
            data.put("FWLXMC", serveType.getName());
            data.put("DABJ", lossQuotationItem.isProductRule() ? 1 : 0);
            data.put("F_GSID", lossQuotation.getCompany().getId());
            data.put("GSID", lossQuotation.getCompany().getId());
            data.put("PTID", platform.getId());
            data.put("PTMC", platform.getName());
            data.put("CZY", creator.getName());
            data.put("ZDR", creator.getName());
            data.put("ZDRQ_SJ", new Date());

            if (Objects.equals("B",lossQuotation.getOrderType().getCode())) {
                data.put("MDID", lossQuotation.getGetCarDept().getOrigin());
                data.put("MDMC", lossQuotation.getGetCarDept().getName());
                data.put("FWMDID", lossQuotation.getGetCarDept().getOrigin());
                data.put("FWMDMC", lossQuotation.getGetCarDept().getName());
            }else {
                data.put("MDID", fixedLossDept.getOrigin());
                data.put("MDMC", fixedLossDept.getName());
                data.put("FWMDID", fixedLossDept.getOrigin());
                data.put("FWMDMC", fixedLossDept.getName());
            }
            data.put("CJHM", lossQuotation.getCustomerExpand().getVin());
            data.put("PZCXID", lossQuotation.getCustomerExpand().getJekunModelCode());
            data.put("PZCXMC", lossQuotation.getCustomerExpand().getCarModelLabel());

            try {
                data.put("FWFAZDR",SpringManager.getBean(PartyRoleRepository.class).findOne(lossQuotation.getCreator()).getName());
            }catch (Exception e){
                throw new RuntimeException("方案制单人实体不存在");
            }
            JSONArray itemArray = new JSONArray();
            int index = 0;
            values.forEach(item -> {
                CommodityInquiryItem commodityInquiryItem = new CommodityInquiryItem();
                commodityInquiryItem.setProductId(item.getProduct());
                commodityInquiryItem.setOriginalProductId(item.getProduct());
                commodityInquiryItem.setFitting(item.getFitting());
                commodityInquiryItem.setProductUomId(item.getUom());

                commodityInquiryItem.setSalesVolume(item.getSaleQty());
                commodityInquiryItem.setDeliverables(item.getSaleQty());
                commodityInquiryItem.setSupplyStatus(servicePlanceService.findCommotidyHY());
                commodityInquiryItem.setCompanyId(item.getLocation().getCompany());

                commodityInquiryItem.setUnitPrice(0);
                commodityInquiryItem.setPartCode(item.getPartCode());
                commodityInquiryItem.setPartName(item.getPartName());
                commodityInquiryItem.setSaleLimit(item.getFloorPrice());
                commodityInquiryItem.setInquiryType(item.getInquiryType());
                commodityInquiryItem.setSummary(item.getRemarks());
                commodityInquiryItem.setMapAddress(item.getMapAddress());
                commodityInquiryItem.setImageSN(item.getImageSN());
                JSONObject result = new JSONObject();
                result = commodityInquiryOrderService.formatSPXJDMX(result,commodityInquiryItem);
                result.put("XH", index +1);
                itemArray.add(result);

                boolean excluClassifyFlag = invoke("mdm.supplierBusinessScopeService.externalCallBusinessScopeClassify",
                        MapUtil.mapper("supplierId", findBaturuSupplier.get(0).getValue(), "classifyId", item.getProduct().getClassify().getId()));
                if (!wantInvoiceFlag && isExistsPurGroup && scopeCarFlag && excluClassifyFlag) this.baturuInquireData(item, inquireData, platform);
            });
            data.put("PUR_SPXJDMX", itemArray);
            array.add(data);
        });
        commodityInquiryOrderService.createSynSPXJD(array, lossQuotation.getInnerBusinessKey());
        //if (!wantInvoiceFlag && isExistsPurGroup && scopeCarFlag) invoke("fn.servicePlan.servicePlanToInquire", inquireData);
    }

    private boolean judgeSendInquiryPurGroup(String storeId, String purchasingGroupId) {
        boolean isExistsPurchasGrouop = invoke("cm.purchasingGroupService.accordStoreIdFind", MapUtil.mapper("storeId", storeId, "purchasingGroupId", purchasingGroupId));
        return isExistsPurchasGrouop;
    }

    // 转询价 - 巴图鲁询价
    private void baturuInquireMainData(LossQuotation lossQuotation, JSONObject inquireData, Map inquireOtherInfo) {
        String store = lossQuotation.getGetCarDept().getOrigin();
        if (Objects.equals("B", lossQuotation.getOrderType().getCode())) {
            store = deptRepository.findOne(lossQuotation.getGetCarDept().getId()).getOrigin();
        }else {
            store = deptRepository.findOne(lossQuotation.getFixedLossDept().getId()).getOrigin();
        }
        inquireData.put("origin", lossQuotation.getInnerBusinessKey());
        inquireData.put("originBusinessType", lossQuotation.getInnerBusinessType());
        inquireData.put("store", store);

        List contractPersons = lossQuotationRepository.findAll("SELECT (SELECT RYID FROM MAS_BJZRY@DB_OLDERP B WHERE B.BJZ = A.BJZ AND ROWNUM = 1) FROM MAS_DDXX@DB_OLDERP A WHERE DDID = '"+ store +"'");
        String inquirePerson = contractPersons.isEmpty()?"":contractPersons.get(0).toString();
        User user = new User();
        if (StringUtils.hasText(inquirePerson)) user = SpringManager.getBean(UserRepository.class).findByOrigin(inquirePerson);
        inquireData.put("publishNew", true);
        inquireData.put("contactPerson", inquirePerson);
        inquireData.put("contactPhone", ObjectUtils.isEmpty(user)?"":user.getMobileNumber());


        Location location = locationRepository.findByDept(lossQuotation.getGetCarDept().getId()).get(0);
        PhyDepot phyDepot = location.getPhyDepot();
        JSONObject receiverAddress = new JSONObject();
        receiverAddress.put("location", phyDepot.getLongitude() +"," + phyDepot.getLatitude());
        receiverAddress.put("address", phyDepot.getAddress());
        inquireData.put("inquiryAddress", receiverAddress);

        // 车辆信息
        JSONArray carInfos = new JSONArray();
        JSONObject carInfo = new JSONObject();
        carInfo.put("vinCode", lossQuotation.getCustomerExpand().getVin());
        carInfo.put("jekunModelCode", lossQuotation.getCustomerExpand().getJekunModelCode());
        carInfo.put("carModelLabel", lossQuotation.getCustomerExpand().getCarModelLabel());
        carInfo.put("carLicense", lossQuotation.getCustomerExpand().getCarLicense());
        carInfo.put("nameplatePicture", inquireOtherInfo.get("nameplatePicture"));
        carInfo.put("headPicture", inquireOtherInfo.get("headPicture"));
        carInfo.put("trailPicture", inquireOtherInfo.get("trailPicture"));

        List oldQccxpzs = lossQuotationRepository.findAll("SELECT QCPPMC, CHXID, QCCPMC FROM MAS_QCCXPZ@DB_OLDERP WHERE PZCXID = '"+ lossQuotation.getCustomerExpand().getJekunModelCode() +"'");
        if (!oldQccxpzs.isEmpty()) {
            Object[] carInfosO = ((Object[])oldQccxpzs.get(0));
            carInfo.put("carBrandName", carInfosO[0]);
            carInfo.put("carSystemName", carInfosO[1]);
            carInfo.put("carManuFacturer", carInfosO[2]);
            carInfo.put("carType", carInfosO[1]);
        }
        carInfos.add(carInfo);
        inquireData.put("carInfos", carInfos);
    }

    // 转询价 - 巴图鲁询价明细
    private void baturuInquireData(LossQuotationItem item, JSONObject inquireData, PartyRole platform) {
        // epc 获取配件名称需要判断是否已编译
        JSONArray inquiryDetails = new JSONArray();
        JSONObject inquiryDetail = new JSONObject();

        if ("E01".equals(item.getPartCode()) || StringUtils.hasText(item.getPartCode())) { // E01 表示高低配
            String partyName = item.getProduct().getCategory().getName().indexOf("待编译") == -1?item.getProduct().getCategory().getName():item.getPartName();
            inquiryDetail.put("partsName", partyName);
            if (!"E01".equals(item.getPartCode())) inquiryDetail.put("partsCode", item.getPartCode());
        } else {
            inquiryDetail.put("partsName", item.getProduct().getCategory().getName());
        }

        inquiryDetail.put("partsName", /*item.getPartName()*/item.getProduct().getCategory().getName()); // ????????
        inquiryDetail.put("partsCode", item.getPartCode()); // ???????? oe号，还是商品的 oem？
        inquiryDetail.put("remark", item.getRemarks() + item.getPartCode());
        inquiryDetail.put("platformId", platform.getId());
        inquiryDetail.put("partsId", item.getProduct().getId());
        inquiryDetail.put("threePartyDetailCode", item.getProduct().getId());
        inquiryDetail.put("originProduct", item.getProduct().getId());
        inquiryDetail.put("pictures", servicePlanceService.obtainTagImages(item.getTagMapAddress()));

        inquiryDetail.put("productRule", item.isProductRule() ? 1 : 0);
        inquiryDetails.add(inquiryDetail);
        if (inquireData.containsKey("inquiryDetails")) {
            JSONArray inquiryDetailsAppend =inquireData.getJSONArray("inquiryDetails");
            inquiryDetailsAppend.addAll(inquiryDetails);
        } else {
            inquireData.put("inquiryDetails", inquiryDetails);
        }
    }


    /**
     * 获取询价商品，根据服务类型分组
     * @param lossQuotation
     */
    public Map<String,List<LossQuotationItem>> getInquiryGoods(LossQuotation lossQuotation, JSONArray array,String state){
        Map<String,List<LossQuotationItem>> groupMap = new HashMap<String,List<LossQuotationItem>>();
        PartyRole platform = SpringManager.getBean(FnCommunalService.class).getPlatform(false, true, lossQuotation.getFixedLossDept());
        List<LossQuotationItem> list = lossQuotation.getLossQuotationItems().stream().filter(lossQuotationItem -> {
            return lossQuotationItem.isNeedInquiry()&&("10".equals(lossQuotationItem.getProduct().getProductGroup().getId())||lossQuotationItem.isProductRule());
        }).collect(toList());
        groupMap= list.stream().collect(groupingBy((item)->{
            return  item.getServeType().getId() + platform.getId() + item.isProductRule();
        }));
        return groupMap;
    }


    /**
     * 设置获取商品
     * @param lossQuotation
     */
    public void setGetPriseGoods(LossQuotation lossQuotation, JSONArray getPriceGoodsArray){
        lossQuotation.getLossQuotationItems().forEach((lossQuotationItem)->{
            getPriceGoodsArray.forEach((item)->{
                JSONObject tempJson = (JSONObject)item;
                //当最低定损单价 和销售单价为零时 才去更新 数据
                if(lossQuotationItem.getId().equals(tempJson.getString("id"))
                        && (lossQuotationItem.getMinimumPrice() <=0 || lossQuotationItem.getSalePrice() <= 0)){
                    addInquiryParas(lossQuotationItem,tempJson);
                }
            });
        });
    }

    /**
     * 询价改变的商品
     * @param lossQuotationItem
     * @param inquiryJson
     */
    private void addInquiryParas(LossQuotationItem lossQuotationItem, JSONObject inquiryJson){

        lossQuotationItem.setMinimumPrice(inquiryJson.getDoubleValue("P008"));
        lossQuotationItem.setSalesAmount(inquiryJson.getDoubleValue("XSSL") * inquiryJson.getDoubleValue("S901"));
        lossQuotationItem.setOriginalInquiryProduct(lossQuotationItem.getProduct());
        lossQuotationItem.setExpectedArrivalTime(inquiryJson.getDoubleValue("YJDHSC"));
        lossQuotationItem.setInquiryGooodsState(inquiryJson.getString("HYZT"));

        lossQuotationItem.setDiscountRate(inquiryJson.getDoubleValue("Z002") == 0 ? 0 : inquiryJson.getDoubleValue("S901")/inquiryJson.getDoubleValue("Z002"));
        lossQuotationItem.setClerkPriceLimit(inquiryJson.getDoubleValue("S801"));
        lossQuotationItem.setShopOwnerPriceLimit(inquiryJson.getDoubleValue("S802"));
        lossQuotationItem.setCsoPriceLimit(inquiryJson.getDoubleValue("S803"));
        lossQuotationItem.setBasePrice(inquiryJson.getDoubleValue("Z002"));
        lossQuotationItem.setFloorPrice(inquiryJson.getDoubleValue("P005"));
        lossQuotationItem.setPriceCostUnitExTax(inquiryJson.getDoubleValue("CGDJ"));
        lossQuotationItem.setPriceCostUnitInTax(inquiryJson.getDoubleValue("CGDJ"));
        lossQuotationItem.setPlatformPriceCosInTax(inquiryJson.getDoubleValue("CGDJ"));
        lossQuotationItem.setPrimaryPriceUnit(inquiryJson.getDoubleValue("Z002"));
        lossQuotationItem.setSalePrice(inquiryJson.getDoubleValue("S901"));
        lossQuotationItem.setPftPriceUnit(inquiryJson.getDoubleValue("S901"));
        lossQuotationItem.setSupplyChainManagement(inquiryJson.getDoubleValue("P006") * inquiryJson.getDoubleValue("P008")); //供应链管理费用
        lossQuotationItem.setReferTax(inquiryJson.getDoubleValue("P008")); //供应链管理费用
        if (Objects.equals("0",inquiryJson.getString("HYZT"))){
            lossQuotationItem.setService(false);
            lossQuotationItem.setInsurance(false);
            lossQuotationItem.setAgree(false);
        }else {
            lossQuotationItem.setService(true);
            lossQuotationItem.setInsurance(true);
            lossQuotationItem.setAgree(true);
        }
        lossQuotationItem.setOldInquiryNumber(inquiryJson.getString("XJDH"));

        lossQuotationItem.setOriginalInquiryProduct(lossQuotationItem.getProduct());
    }

    /**
     * 询价改变的商品
     * @param lossQuotationItem
     * @param
     */
    private void addInquiryPrice(LossQuotationItem lossQuotationItem, JSONObject queryJson){
        lossQuotationItem.setMinimumPrice(queryJson.getDoubleValue("referTax"));
        lossQuotationItem.setSalesAmount(queryJson.getDouble("XSSL") * queryJson.getDouble("priceUnit"));
        lossQuotationItem.setOriginalInquiryProduct(lossQuotationItem.getProduct());
        lossQuotationItem.setExpectedArrivalTime(queryJson.getDouble("YJDHSC") == null ? 0 : queryJson.getDouble("YJDHSC"));
        lossQuotationItem.setInquiryGooodsState(queryJson.getString("HYZT"));

        lossQuotationItem.setDiscountRate(queryJson.getDouble("discountRate"));
        lossQuotationItem.setClerkPriceLimit(queryJson.getDouble("clerkPriceLimit"));
        lossQuotationItem.setShopOwnerPriceLimit(queryJson.getDouble("shopOwnerPriceLimit"));
        lossQuotationItem.setCsoPriceLimit(queryJson.getDouble("csoPriceLimit"));
        lossQuotationItem.setBasePrice(queryJson.getDouble("basePrice"));
        lossQuotationItem.setFloorPrice(queryJson.getDouble("floorPrice"));
        lossQuotationItem.setPriceCostUnitExTax(queryJson.getDouble("priceCostUnitExTax"));
        lossQuotationItem.setPriceCostUnitInTax(queryJson.getDouble("priceCostUnitInTax"));
        lossQuotationItem.setPlatformPriceCosInTax(queryJson.getDouble("platformPriceCosInTax"));
        lossQuotationItem.setPrimaryPriceUnit(queryJson.getDouble("primaryPriceUnit"));
        lossQuotationItem.setSalePrice(queryJson.getDouble("priceUnit"));
        lossQuotationItem.setPftPriceUnit(queryJson.getDouble("pftPriceUnit"));
        lossQuotationItem.setSupplyChainManagement(queryJson.getDoubleValue("supplyChainManagement")); //供应链管理费用
        lossQuotationItem.setReferTax(queryJson.getDoubleValue("referTax")); //供应链管理费用
        if (Objects.equals("0",queryJson.getString("HYZT"))){
            lossQuotationItem.setService(false);
            lossQuotationItem.setInsurance(false);
            lossQuotationItem.setAgree(false);
        }else {
            lossQuotationItem.setService(true);
            lossQuotationItem.setInsurance(true);
            lossQuotationItem.setAgree(true);
        }
        lossQuotationItem.setOldInquiryNumber(queryJson.getString("XJDH"));
    }

    /**
     * 创建服务方案单
     * @param
     */
    private ServicePlan createServicePlan(ServicePlan basePlan,LossQuotation lossQuotation) {
        Dept fixedLossDept = lossQuotation.getFixedLossDept();
        boolean flag = Objects.equals(lossQuotation.getGetCarDept().getId(), fixedLossDept.getId());
        Map map = MapUtil.mapped(basePlan);
        ServicePlan servicePlan= MapUtil.getO(map,ServicePlan.class); //新的方案
        if (Objects.equals("委托定损",lossQuotation.getOrderType().getName())) {
            //委托定损创建接车门店的服务方案, 不需要创建定损门店的服务方案
            //设置门店服务方案协助类型为普通
            Dept dept = lossQuotation.getGetCarDept();
            BusinessAttributeValue assistType = SpringManager.getBean(BusinessAttributeValueRepository.class).findOne("ServicePlanItem.assistType.normal");
            Location location  = locationRepository.findAll(JpaDsl.toCriteriaByEq("depot.dept.id",dept.getId(),"usage.id","1")).stream().findFirst().orElse(null);
            servicePlan.getServicePlanItems().forEach(
                    item -> {
                        item.setLocation(location);
                        item.setAssistType(assistType);
                    }
            );
            servicePlan.setPlanType("common");
            servicePlan.setSaleDept(dept);
            servicePlan.setServiceDept(dept);
            servicePlan.setBelongDept(dept);
            double claimAmount = servicePlan.getServicePlanItems()
                    .stream().mapToDouble(
                            item -> Arith.mul(item.getPftPriceUnit(), item.getSaleQty())

                    ).sum();
            servicePlan.setClaimAmount(Arith.round(claimAmount,2));
            servicePlan = this.invoke("fn.service.createForInvoke", MapUtil.mapped(servicePlan));
            return servicePlan;
        }else {
            if (!flag) {
                //创建 一个门店服务方案 把销售门店 ,所属门店改为 门店
                getStorePlanData(lossQuotation, servicePlan);
                servicePlan = this.invoke("fn.service.createForInvoke", MapUtil.mapped(servicePlan));
                //创建j基地的服务方案
                for (ServicePlanItem item : basePlan.getServicePlanItems()) {
                    for (ServicePlanItem servicePlanItem :servicePlan.getServicePlanItems()) {
                        if (item.getProduct().getId().equals(servicePlanItem.getProduct().getId())){
                            item.setParentServicePlanItem(servicePlanItem);
                        }
                    }
                }
                basePlan.setPlanType("allAssist");
            } else {
                basePlan.setPlanType("common");
            }
            basePlan = this.invoke("fn.service.createForInvoke", MapUtil.mapped(basePlan));
            //门店方案需要自动确认
            if (!flag){
                this.invoke("fn.service.confirmForInvoke", MapUtil.mapped(servicePlan));
                servicePlanceService.toInnerItemWrite(basePlan);
            }
            servicePlanceService.submitSynGYSXJD(lossQuotation.getId());
            return basePlan ;
        }
    }

    /**
     * 获取门店服务方案数据
     * @param lossQuotation
     * @param servicePlan
     */
    private void getStorePlanData(LossQuotation lossQuotation, ServicePlan servicePlan) {
        Dept dept = lossQuotation.getGetCarDept();
        Dept base = lossQuotation.getFixedLossDept();
        servicePlan.setSaleDept(dept);
        servicePlan.setBelongDept(dept);
        servicePlan.setPlanType("allAssist");
        //设置门店服务方案协助类型为内协
        BusinessAttributeValue assistType = SpringManager.getBean(BusinessAttributeValueRepository.class).findOne("ServicePlanItem.assistType.inner");
        if (assistType == null) throw new  RuntimeException("服务方案协助类型不存在!!!");
        boolean flg = Objects.equals(dept.getCompany().getId(), base.getCompany().getId());
        //如果是跨公司得则需要取自己得仓库库区
        if (!flg) {
            Location location  = locationRepository.findAll(JpaDsl.toCriteriaByEq("depot.dept.id",dept.getId(),"usage.id","1")).stream().findFirst().orElse(null);
            servicePlan.getServicePlanItems().forEach(
                    item -> {
                        item.setLocation(location);
                        item.setAssistType(assistType);
                    }
            );
        }
        servicePlan.getServicePlanItems().forEach(
                item  -> {
                    item.setMainSaler(SpringManager.getBean(PartyRoleRepository.class).findOne("yyadmin"));
                }
        );
    }

    /***
     * 通过询价单对应的供应商对定损单进行分组
     */
    private void divideItems(LossQuotation lossQuotation, SimpleRequest request) {

        //验证要货的时候，是否能够要货
        checkShutDownProduct(lossQuotation);

        PartyRole platForm_1007 = SpringManager.getBean(PartyRoleService.class).findOne("1007","Company");

        List<LossQuotationItem> lossQuotationItems = lossQuotation.getLossQuotationItems().stream().filter(
                lossQuotationItem -> lossQuotationItem.getRequireQty() > 0
        ).collect(toList());
        if (lossQuotationItems.size() == 0) throw new RuntimeException("要货申请,必须填写要货数量!!!");
        for (LossQuotationItem lossQuotationItem : lossQuotationItems) {
            reSearchLocation(lossQuotation, lossQuotationItem);
        }
        LossQuotation requirePlan = new LossQuotation();
        BeanUtils.copyProperties(lossQuotation,requirePlan,"version","innerBusinessKey","lossQuotationItems","lossQuotationPlans");
        requirePlan.setLossQuotationItems(lossQuotationItems);
        Object invoke = invoke("stock.productRequireService.externalCreate", MapUtil.mapped(requirePlan));

    }

    private void reSearchLocation(LossQuotation lossQuotation, LossQuotationItem lossQuotationItem) {
        if (Objects.equals("委托定损",lossQuotation.getOrderType().getName())) {
            Location location = SpringManager.getBean(LocationService.class)
                    .findLocationByDept(lossQuotation.getGetCarDept(),lossQuotationItem.isProductRule());
            if (Objects.isNull(location)) {
                throw new RuntimeException("未找到接车门店对应的仓库信息!!!");
            }
            lossQuotationItem.setLocation(location);
        }
    }

    /**
     * 创建要货单
     * @param
     */
    private void structRequireGoods(LossQuotation lossQuotation,List<LossQuotationItem> lossQuotationItems, SimpleRequest request) {

        //过滤定损单需要要货的商品(并按照平台，仓库，服务类型进行分组，生成多张要货单)
        lossQuotationItems.stream().collect(groupingBy((x)->{
            return x.getLocation().getCompany().getId()+x.getLocation().getId() + x.getPlatform().getId() + x.getProduct().queryServeType().getId();
        })).forEach((key,values)->{

            //封装要货单主表数据
            LossQuotationItem quotationItem = values.stream().findFirst().orElse(new LossQuotationItem());
            ProductRequire productRequire = new ProductRequire();
            productRequire.setCreator(getPersonId(request));
            productRequire.setCreateDate(new Date());
            productRequire.setSource(lossQuotation.getId());
            productRequire.setSourceBusinessType(lossQuotation.getInnerBusinessType());
            productRequire.setSourceBusinessTypeName(lossQuotation.getBusinessTypeName());

            String store = Objects.equals("B", lossQuotation.getOrderType().getCode())?lossQuotation.getGetCarDept().getId():lossQuotation.getFixedLossDept().getId();
            productRequire.setStore(getBean(StoreRepository.class).findByDept(deptRepository.findOne(store)));
            //如果定损单是委托定损, 则需要生成接车门店的要货单
            if (Objects.equals("委托定损",lossQuotation.getOrderType().getName())) {
                Location location = SpringManager.getBean(LocationService.class)
                        .findLocationByDept(lossQuotation.getGetCarDept(),quotationItem.isProductRule());
                if (Objects.isNull(location)) {
                    throw new RuntimeException("未找到接车门店对应的仓库信息!!!");
                }
                productRequire.setLocation(location);
            }else {
                productRequire.setLocation(quotationItem.getLocation());
            }
            productRequire.setCustomerExpand(lossQuotation.getCustomerExpand());
            PartyRole locationCompany = productRequire.getLocation().getCompany();
            productRequire.setCompany(locationCompany);
            productRequire.setPlatform(quotationItem.getPlatform());

            //封装要货单明细表数据
            for (LossQuotationItem lossQuotationItem : values) {
                ProductRequireItem productRequireItem = new ProductRequireItem();
                productRequireItem.setProductRequire(productRequire);
                productRequireItem.setCompany(locationCompany);
                productRequireItem.setProduct(lossQuotationItem.getProduct());
                productRequireItem.setUom(lossQuotationItem.getUom());
                productRequireItem.setQtyRequire(lossQuotationItem.getRequireQty());
                productRequireItem.setCommodityInquiryOrderId(lossQuotationItem.getOldInquiryNumber());
                productRequireItem.setSupplier(lossQuotationItem.getSupplier());
                productRequireItem.setUniqueValue(lossQuotationItem.getUniqueValue());
                productRequireItem.setExpectedArrivalTime(lossQuotationItem.getExpectedArrivalTime());
                if (StringUtils.hasText(productRequireItem.getCommodityInquiryOrderId())) {
                    productRequireItem.setSourceState(enumerationRepository.findAll(JpaDsl.toCriteriaByEq("type.id", "supplyStatus", "code", lossQuotationItem.getInquiryGooodsState())).stream().findFirst().orElse(null));
                } else {
                    productRequireItem.setSourceState(enumerationRepository.findOne("003334"));
                }
                getCommodiInquireSupplier(lossQuotationItem.getOldInquiryNumber(), lossQuotationItem.getProduct().getId(), productRequireItem);
                productRequire.getProductRequireItems().add(productRequireItem);
                if (Objects.nonNull(lossQuotationItem.getPriceForward()) && "1-2-4-5".contains(lossQuotationItem.getPriceForward())){
                    productRequireItem.setSpId(lossQuotationItem.getUniqueValue());
                    productRequireItem.setChannelType(Integer.valueOf(lossQuotationItem.getPriceForward()));
                    productRequireItem.setSupplier(lossQuotationItem.getSupplier());
                    List<PurchasingGroup> purchasingGroups = getBean(PurchasingGroupRepository.class).findDeptAndSupplier(lossQuotation.getFixedLossDept().getId(), lossQuotationItem.getSupplier().getId());
                    if (!purchasingGroups.isEmpty()) {
                        productRequireItem.setPurchasingGroup(purchasingGroups.get(0));
                    }
                    if("2".equals(lossQuotationItem.getPriceForward())){
                        productRequireItem.setOfferId(lossQuotationItem.getUniqueValue());
                    }
                    if("5".equals(lossQuotationItem.getPriceForward())){
                        productRequireItem.setOfferId(lossQuotationItem.getUniqueValue());
                    }
                }
            }
            this.invoke("stock.productRequire.create",productRequire); //新增
            // this.invoke("stock.productRequire.approve",productRequire); //审批

        });
    }

    /** 获取询价执行表供应商 */
    private void getCommodiInquireSupplier(String commodiInquireId, String productId, ProductRequireItem productRequireItem) {
        JSONObject data = SpringManager.getBean(PiManager.class).synErp("spxjdService.getSPXJDZXBInfo", MapUtil.mapper("XJDH", commodiInquireId, "SPID", productId));
        data = JSONObject.parseObject(data.get("obj").toString());
        if (data.get("GYSID") != null) {
            List<ContrastPartyCode> contrastPartyCodeList = SpringManager.getBean(ContrastPartyCodeRepository.class).findAll(JpaDsl.toCriteriaByEq("gysid", data.getString("GYSID")));
            if (contrastPartyCodeList.size() == 0) {
                throw new RuntimeException("请维护角色对照表，供应商编码：" + data.getString("GYSID"));
            }
            productRequireItem.setSupplier(SpringManager.getBean(PartyRoleRepository.class).findAll(JpaDsl.toCriteriaByEq("party.id", contrastPartyCodeList.get(0).getParty().getId(), "role.id", "Supplier")).get(0));
            if (data.get("ZDID") != null) productRequireItem.setSite(SpringManager.getBean(SiteRepository.class).findOne(data.getString("ZDID")));
            if (data.get("CGZID") != null) productRequireItem.setPurchasingGroup(SpringManager.getBean(PurchasingGroupRepository.class).findOne(data.getString("CGZID")));
        }
    }

    private void checkShutDownProduct(LossQuotation lossQuotation) {
        servicePlanceService.checkShutDownProduct(MapUtil.mapper("NEW_DEPT_ID", lossQuotation.getFixedLossDept().getId(),
                "productList", lossQuotation.getLossQuotationItems().stream()
                        .filter(lossQuotationItem -> {
                            return "2".equals(lossQuotationItem.getProduct().getState());
                        }).map(lossQuotationItem -> {
                            return MapUtil.mapper(
                                    "qty", lossQuotationItem.getSaleQty(),
                                    "productId", lossQuotationItem.getProduct().getId(),
                                    "productName", lossQuotationItem.getProduct().getName()
                            );
                        }).collect(Collectors.toList())));
    }

    /**
     * 回写服务方案ID到对应的定损方案上
     * @param
     */
    private void updatePlanIdForDetail(LossQuotation lossQuotation,String servicePlan) {
        List<LossQuotationPlan> set = lossQuotation.getLossQuotationPlans();
        //如果没有定损确认方案,则是提前修车,
        if (set != null && set.size() > 0) {
            lossQuotation.getLossQuotationPlans().forEach(
                    item ->{
                        if(!item.isPayYourself() && StringUtils.isEmpty(item.getServicePlan())) {
                            item.setServicePlan(servicePlan);
                        }
                        //把转服务方案的商品明细标记未完成状态
                        if(!item.isPayYourself()) item.setDone(true);
                    }
            );
            lossQuotation.getLossQuotationItems().forEach(
                    item -> {
                        if(item.isService() && StringUtils.isEmpty(item.getServicePlan())) {
                            item.setServicePlan(servicePlan);
                        }
                    }
            );
        }else {
            lossQuotation.getLossQuotationItems().forEach(
                    item ->{
                        if(item.isAdvanceRepair() && StringUtils.isEmpty(item.getServicePlan())) {
                            item.setServicePlan(servicePlan);
                        }
                    }
            );
        }
    }

    /**
     * 回写定损报价的明细要货商品的已要货数量
     * @param lossQuotation 定损报价单
     */
    private void updateReceivedQty(LossQuotation lossQuotation) {
        lossQuotation.getLossQuotationItems().forEach(
                item -> {
                    //如果要货数量大于0 则 说明需要货,则更新要货数量和已要货数量
                    if (item.getRequireQty() >0) {
                        item.setReceiveQty(item.getReceiveQty() +item.getRequireQty());
                        item.setRequireQty(0);
                    }
                }
        );
    }

    /**
     * 包装生成服务方案单数据
     * @param
     */
    private String packageDataToService(LossQuotation lossQuotation) {
        ServicePlan plan = new ServicePlan();
        Dept fixedLossDept = lossQuotation.getFixedLossDept();
        if (Objects.equals("B",lossQuotation.getOrderType().getCode())) fixedLossDept = lossQuotation.getGetCarDept();
        plan.setCompany(lossQuotation.getCompany());
        plan.setFnCustomerExpand(lossQuotation.getCustomerExpand());
        plan.setSourceFrom(lossQuotation.getId());
        plan.setSourceBusinessType(lossQuotation.getInnerBusinessType());
        plan.setSourceBusinessTypeName(lossQuotation.getBusinessTypeName());
        plan.setBelongDept(fixedLossDept);
        plan.setSaleDept(lossQuotation.getGetCarDept());
        plan.setServiceDept(fixedLossDept);
        plan.setState("submission");
        plan.setSubmissionUid(lossQuotation.getApproveUid());
        plan.setSubmissionDate(new Date());
        plan.setOutSystemBusiness(lossQuotation.isOutSystemBusiness());
        plan.setChannel(SpringManager.getBean(ChannelRepository.class).findOne("10"));
        plan.setServeType(SpringManager.getBean(BusinessAttributeValueRepository.class).findOne("ServicePlan.serveType.A"));
        List<LossQuotationPlan> lossQuotationPlans = getLossQuotationPlans(lossQuotation);

        //正常修车
        if (lossQuotationPlans != null && lossQuotationPlans.size() >0) {
            planRepairCar(plan, lossQuotationPlans);
        }else {
            //提前转服务修车 ,各种价格都为0.01
            advanceRepairCar(lossQuotation, plan);
        }
        return createServicePlan(plan,lossQuotation).getId();
    }

    /**
     * 提前修车
     * @param lossQuotation
     * @param plan
     */
    private void advanceRepairCar(LossQuotation lossQuotation, ServicePlan plan) {
        List<LossQuotationItem> list = getAdvanceRepairGoods(lossQuotation);
        if (list.size() == 0) throw new RuntimeException("提前修车的商品已经全部转修车了,请勿重复审核!!!");
        //去除以修代换得商品
        List<LossQuotationItem> normalList = list.stream().filter(item -> !item.isReplaceWithRepair()).collect(Collectors.toList());
        normalList.forEach(
                item -> {
                    ServicePlanItem servicePlanItem = new ServicePlanItem();
                    servicePlanItem.setPrimaryPriceUnit(0.01);
                    servicePlanItem.setPrimaryPriceUnitShow(0.01);
                    servicePlanItem.setBasePrice(0.01);
                    servicePlanItem.setPriceUnit(0.01);
                    servicePlanItem.setPftPriceUnit(0.01);
                    servicePlanItem.setClerkPriceLimit(0.01);
                    servicePlanItem.setShopOwnerPriceLimit(0.01);
                    servicePlanItem.setCsoPriceLimit(0.01);
                    servicePlanItem.setSalesAmount(0.01);
                    servicePlanItem.setProduct(item.getProduct());
                    servicePlanItem.setSaleQty(item.getSaleQty());
                    servicePlanItem.setLocation(item.getLocation());
                    servicePlanItem.setPriceCostUnitExTax(item.getPriceCostUnitExTax());
                    servicePlanItem.setFloorPrice(item.getFloorPrice());
                    servicePlanItem.setPlatformPriceCosInTax(item.getPlatformPriceCosInTax());
                    servicePlanItem.setPriceCostUnitInTax(item.getPriceCostUnitInTax());
                    servicePlanItem.setUom(item.getUom());
                    servicePlanItem.setManagementFeeRate(0);
                    servicePlanItem.setCarrierId(item.getCarrierId());
                    servicePlanItem.setCarrierName(item.getCarrierName());
                    servicePlanItem.setManagementCost(0);
                    servicePlanItem.setCategory(item.getCategory());
                    servicePlanItem.setPlatform(item.getPlatform());
                    servicePlanItem.setServeType(item.getServeType());
                    servicePlanItem.setServicePlan(plan);
                    servicePlanItem.setExpectedArrivalTime(item.getExpectedArrivalTime());
                    servicePlanItem.setInquiryGooodsState(item.getInquiryGooodsState());
                    servicePlanItem.setFitting(item.getFitting());
                    servicePlanItem.setReferTax(item.getReferTax());
                    servicePlanItem.setSupplyChainManagement(item.getSupplyChainManagement());
                    servicePlanItem.setEstimatedCommission(item.getEstimatedCommission());
                    servicePlanItem.setOldInquiryNumber(item.getOldInquiryNumber());
                    servicePlanItem.setUniqueValue(item.getUniqueValue());
                    servicePlanItem.setProductRule(item.isProductRule());
                    servicePlanItem.setPriceForward(item.getPriceForward());
                    servicePlanItem.setSupplier(item.getSupplier());
                    servicePlanItem.setQuoteResultId(item.getQuoteResultId());
                    plan.getServicePlanItems().add(servicePlanItem);
                }
        );
        //如果存在以修代换商品,则需要算出商品得总金额,用一个特定商品承载
        List<LossQuotationItem> canRepairList = list.stream().filter(LossQuotationItem::isReplaceWithRepair).collect(Collectors.toList());
        if (canRepairList.size() >0) {
            Location location = canRepairList.stream().findFirst().orElse(new LossQuotationItem()).getLocation();
            packageReplaceWithRepairGoods(plan,0.01,location);
        }
    }
    private List<LossQuotationItem> getAdvanceRepairGoods(LossQuotation lossQuotation) {
        return lossQuotation.getLossQuotationItems().stream().filter(
                item -> item.isAdvanceRepair() && StringUtils.isEmpty(item.getServicePlan())
        ).collect(toList());
    }

    private List<LossQuotationItem> getNotPriceGoods(LossQuotation lossQuotation) {
        return lossQuotation.getLossQuotationItems().stream().filter(
                item -> item.getSalePrice()==0
        ).collect(Collectors.toList());
    }

    //获取无货商品 同意标记未false 则表示无货
    private List<LossQuotationItem> getSoldOutGoods(LossQuotation lossQuotation) {
        return lossQuotation.getLossQuotationItems().stream().filter(
                item -> !item.isAgree()
        ).collect(toList());
    }

    /**
     * 正常修车流程
     * @param plan 新增得服务方案
     * @param lossQuotationPlans 确认方案明细
     */
    private void planRepairCar(ServicePlan plan, List<LossQuotationPlan> lossQuotationPlans) {
        List<LossQuotationPlan> list = lossQuotationPlans.stream().filter(item -> !item.isReplaceWithRepair()).collect(Collectors.toList());
        list.forEach(
                item -> {
                    ServicePlanItem servicePlanItem = new ServicePlanItem();
                    servicePlanItem.setPrimaryPriceUnit(item.getFixedLossPrice());
                    servicePlanItem.setPrimaryPriceUnitShow(item.getFixedLossPrice());
                    servicePlanItem.setBasePrice(item.getFixedLossPrice());
                    servicePlanItem.setPriceUnit(item.getFixedLossPrice());
                    servicePlanItem.setPlatform(item.getPlatform());
                    servicePlanItem.setServeType(item.getServeType());
                    servicePlanItem.setPftPriceUnit(item.getFixedLossPrice());
                    servicePlanItem.setClerkPriceLimit(item.getFixedLossPrice());
                    servicePlanItem.setShopOwnerPriceLimit(item.getFixedLossPrice());
                    servicePlanItem.setCsoPriceLimit(item.getFixedLossPrice());
                    servicePlanItem.setSalesAmount(item.getFixedLossAmount());
                    servicePlanItem.setProduct(item.getProduct());
                    servicePlanItem.setSaleQty(item.getSaleQty());
                    servicePlanItem.setLocation(item.getLocation());
                    servicePlanItem.setFloorPrice(item.getFloorPrice());
                    servicePlanItem.setPlatformPriceCosInTax(item.getPlatformPriceCosInTax());
                    servicePlanItem.setPriceCostUnitInTax(item.getPriceCostUnitInTax());
                    servicePlanItem.setPriceCostUnitExTax(item.getPriceCostUnitExTax());
                    servicePlanItem.setCarrierId(item.getCarrierId());
                    servicePlanItem.setCarrierName(item.getCarrierName());
                    servicePlanItem.setManagementFeeRate(0);
                    servicePlanItem.setUom(item.getUom());
                    servicePlanItem.setManagementCost(0);
                    servicePlanItem.setFitting(item.getFitting());
                    servicePlanItem.setCategory(item.getCategory());
                    servicePlanItem.setExpectedArrivalTime(item.getExpectedArrivalTime());
                    servicePlanItem.setInquiryGooodsState(item.getInquiryGooodsState());
                    servicePlanItem.setReferTax(item.getReferTax());
                    servicePlanItem.setSupplyChainManagement(item.getSupplyChainManagement());
                    servicePlanItem.setEstimatedCommission(item.getEstimatedCommission());
                    servicePlanItem.setOldInquiryNumber(item.getOldInquiryNumber());
                    // servicePlanItem.setAssistType(SpringManager.getBean(BusinessAttributeValueRepository.class).findOne("ServicePlanItem.assistType.normal"));
                    servicePlanItem.setServicePlan(plan);
                    servicePlanItem.setProductRule(item.isProductRule());
                    servicePlanItem.setUniqueValue(item.getUniqueValue());
                    servicePlanItem.setPriceForward(item.getPriceForward());
                    servicePlanItem.setSupplier(item.getSupplier());

                    servicePlanItem.setQuoteResultId(item.getQuoteResultId());
                    plan.getServicePlanItems().add(servicePlanItem);
                }
        );
        double claimAmount = plan.getServicePlanItems()
                .stream().mapToDouble(
                        item -> Arith.mul(item.getPftPriceUnit(), item.getSaleQty())

                ).sum();
        plan.setClaimAmount(claimAmount);
        //如果存在以修代换商品,则需要算出商品得总金额,用一个特定商品承载
        List<LossQuotationPlan> canRepairList = lossQuotationPlans.stream().filter(LossQuotationPlan::isReplaceWithRepair).collect(Collectors.toList());
        if (canRepairList.size() >0 ) {
            double totalAmount = canRepairList.stream().mapToDouble(LossQuotationPlan::getFixedLossAmount).sum();
            Location location = canRepairList.stream().findFirst().orElse(new LossQuotationPlan()).getLocation();
            packageReplaceWithRepairGoods(plan,totalAmount,location);
        }
    }

    /**
     * 包装以修代换商品数据
     *
     */
    private void packageReplaceWithRepairGoods(ServicePlan plan,double amount,Location location) {
        LossAssessmentGoods assessmentGoods  =
                assessmentGoodsRepository.findAll(JpaDsl.toCriteriaByEq("useType","2")).stream().findFirst().orElse(null);
        if (assessmentGoods == null){
            throw new RuntimeException("定损专用商品未定义,请联系后台人员!!!!");
        }
        Product product = assessmentGoods.getProduct();
        ServicePlanItem servicePlanItem = new ServicePlanItem();
        servicePlanItem.setPrimaryPriceUnit(amount);
        servicePlanItem.setBasePrice(amount);
        servicePlanItem.setPriceUnit(amount);
        servicePlanItem.setPlatform(SpringManager.getBean(PartyRoleRepository.class).findOne("1007"));
        servicePlanItem.setPrimaryPriceUnitShow(amount);
        // servicePlanItem.setServeType(item.getServeType());
        servicePlanItem.setPftPriceUnit(amount);
        servicePlanItem.setClerkPriceLimit(amount);
        servicePlanItem.setShopOwnerPriceLimit(amount);
        servicePlanItem.setCsoPriceLimit(amount);
        servicePlanItem.setSalesAmount(amount);
        servicePlanItem.setProduct(product);
        servicePlanItem.setSaleQty(1);
        servicePlanItem.setLocation(location);
        servicePlanItem.setFloorPrice(0);
        servicePlanItem.setPlatformPriceCosInTax(0);
        servicePlanItem.setPriceCostUnitInTax(0);
        servicePlanItem.setPriceCostUnitExTax(0);
        servicePlanItem.setManagementFeeRate(0);
        servicePlanItem.setUom(product.getUom());
        servicePlanItem.setManagementCost(0);
        // servicePlanItem.setFitting(item.getFitting());
        servicePlanItem.setCategory(product.getCategory());
        // servicePlanItem.setExpectedArrivalTime(0);
        // servicePlanItem.setInquiryGooodsState();
        // servicePlanItem.setReferTax(item.getReferTax());
        // servicePlanItem.setSupplyChainManagement(item.getSupplyChainManagement());
        // servicePlanItem.setEstimatedCommission(item.getEstimatedCommission());
        // servicePlanItem.setOldInquiryNumber(item.getOldInquiryNumber());
        servicePlanItem.setServicePlan(plan);
        plan.getServicePlanItems().add(servicePlanItem);

    }

    /**
     * 生成定损确认方案
     * @param
     */
    private boolean createLossQuotationPlan(LossQuotation lossQuotation) {
        List<LossQuotationItem> lossQuotationItems =
                lossQuotation.getLossQuotationItems().stream().filter(
                        item -> {
                            return (item.isService() && StringUtils.isEmpty(item.getServicePlan()))
                                    || (item.isService() && !StringUtils.isEmpty(item.getServicePlan()) && !item.isPlan())  ;

                        }
                ).collect(toList());
        if (lossQuotationItems.size() == 0){
            return true;
        }
        lossQuotationItems.forEach(
                item -> {
                    if (item.getMinimumPrice() <= 0 || item.getSalePrice() <= 0) {
                        throw new RuntimeException("商品编码为:" + item.getProduct().getId() + " 价格为零,不能确认方案,请转询价!!!");
                    }
                    if (item.isPlan()){
                        return;
                    }
                    LossQuotationPlan lossQuotationPlan = new LossQuotationPlan();
                    lossQuotationPlan.setProduct(item.getProduct());
                    lossQuotationPlan.setLocation(item.getLocation());
                    lossQuotationPlan.setUom(item.getUom());
                    lossQuotationPlan.setSaleQty(item.getSaleQty());
                    lossQuotationPlan.setLocation(item.getLocation());
                    lossQuotationPlan.setSaleQty(item.getSaleQty());
                    lossQuotationPlan.setProductRule(item.isProductRule());
                    lossQuotationPlan.setMinFixedLossPrice(item.getMinimumPrice());
                    lossQuotationPlan.setMinFixedLossAmount(item.getMinimumPrice()*item.getSaleQty());
                    lossQuotationPlan.setPriceCostUnitExTax(item.getPriceCostUnitExTax());
                    lossQuotationPlan.setPriceCostUnitInTax(item.getPriceCostUnitInTax());
                    lossQuotationPlan.setSalesAmount(item.getSalesAmount());
                    lossQuotationPlan.setPlatform(item.getPlatform());
                    lossQuotationPlan.setServeType(item.getServeType());
                    lossQuotationPlan.setServicePlan(item.getServicePlan());
                    lossQuotationPlan.setFloorPrice(item.getMinimumPrice());
                    lossQuotationPlan.setPlatformPriceCosInTax(item.getPlatformPriceCosInTax());
                    lossQuotationPlan.setBasePrice(item.getBasePrice());
                    lossQuotationPlan.setCategory(item.getCategory());
                    lossQuotationPlan.setCarrierId(item.getCarrierId());
                    lossQuotationPlan.setCarrierName(item.getCarrierName());
                    lossQuotationPlan.setCategory(item.getCategory());
                    lossQuotationPlan.setLossQuotation(lossQuotation);
                    lossQuotationPlan.setDividendStore(lossQuotation.getDividendStore());
                    lossQuotationPlan.setDividendStoreOld(lossQuotation.getDividendStore());
                    lossQuotationPlan.setExpectedArrivalTime(item.getExpectedArrivalTime());
                    lossQuotationPlan.setInquiryGooodsState(item.getInquiryGooodsState());
                    lossQuotationPlan.setSupplyChainManagement(item.getSupplyChainManagement());
                    lossQuotationPlan.setEstimatedCommission(item.getEstimatedCommission());
                    lossQuotationPlan.setReferTax(item.getReferTax());
                    lossQuotationPlan.setOldInquiryNumber(item.getOldInquiryNumber());
                    lossQuotationPlan.setUniqueValue(item.getUniqueValue());
                    lossQuotationPlan.setReplaceWithRepair(item.isReplaceWithRepair());
                    lossQuotationPlan.setPriceForward(item.getPriceForward());
                    lossQuotationPlan.setSupplier(item.getSupplier());
                    lossQuotationPlan.setQuoteResultId(item.getQuoteResultId());
                    lossQuotation.getLossQuotationPlans().add(lossQuotationPlan);
                    //将确认方案的商品的已确认方案标记打上
                    item.setPlan(true);
                }

        );
    return false;
    }


    /**
     * 根据车险报案单查询定损方案
     * @param
     */
    private List<LossQuotationPlan> findPlanByCarAccident(SimpleRequest request) {
        JSONObject param = request.getJO();
        if (StringUtils.isEmpty(param.getString("carAccident"))) {
            throw new RuntimeException("车险报案单号不能为空!!!");
        }
        return lossQuotationRepository.findPlanByCarAccident(param.getString("carAccident"));
    }


    /**
     * 根据单号和商品回写定损报价单数据
     * @param list 商品明细
     * @param lossQuotationID:定时报价单号
     */
    public void writeBackLossQuotation(List<Product> list,String lossQuotationID) {
        LossQuotation lossQuotation = lossQuotationRepository.findOne(lossQuotationID);
        if (lossQuotation == null){
            throw new RuntimeException("未找到对应的定损报价单,单号:" + lossQuotationID);
        }
        if (list.size() == 0) {
            throw new RuntimeException("商品明细不能为空");
        }
        lossQuotation.getLossQuotationItems().forEach(
                item -> {
                    if (item.isAdvanceRepair() || item.isService()) {
                        for (Product product : list) {
                            //终止时,只要是以修代换特定商品, 则需要清空所以有以修代换标记得商品
                            LossAssessmentGoods goods = assessmentGoodsRepository.findOne(product.getId());
                            if (Objects.nonNull(goods)){
                                if (item.isReplaceWithRepair()) {
                                    item.setPlan(false);
                                    item.setServicePlan(null);
                                }
                            }
                            if (item.getProduct().getId().equals(product.getId())) {
                                item.setPlan(false);
                                item.setServicePlan(null);
                            }
                        }
                    }
                }
        );
        //根据终止商品删除掉确认方案对应的明细
        lossQuotation.setLossQuotationPlans(
                lossQuotation.getLossQuotationPlans().stream().filter(
                        item -> {
                            int index = 0;
                            if (!item.isPayYourself()) {
                                for (Product product : list) {
                                    //终止时,只要是以修代换特定商品, 则需要清空所以有以修代换标记得商品
                                    LossAssessmentGoods goods = assessmentGoodsRepository.findOne(product.getId());
                                    if (Objects.nonNull(goods)){
                                        if (item.isReplaceWithRepair()){
                                            index =1;
                                            break;
                                        }
                                    }else if  (item.getProduct().getId().equals(product.getId())) {
                                        index = 1;
                                        break;
                                    }
                                }

                            }
                            return item.isPayYourself() || index ==0;
                        }
                ).collect(toList())
        );
        //设定损报价单状态为新增
        lossQuotation.setState("create");
        SpringManager.getBean(LossQuotationService.class).addLossQuotationLogger(lossQuotation,"方案终止退回","");
        try {
            lossQuotationRepository.saveAndFlush(lossQuotation);
        } catch (Exception e) {
            throw new RuntimeException("回写定损报价单数据报错!!!");
        }
    }

    /**
     * 取消终止报价
     * @return
     */
    @Listener(topic = "event:fn.lossQuotation.backInquiry")
    public LossQuotation backInquiry(SimpleRequest simpleRequest){
        JSONObject tempJson = simpleRequest.getJO();
        LossQuotation lossQuotation = lossQuotationRepository.findOne(tempJson.getString("sourceBusinessKey"));
        if(lossQuotation == null) throw new RuntimeException("来源单据有误，无法退回询价，来源方案缺失");
        lossQuotation.setState("create");
        return lossQuotationRepository.saveAndFlush(lossQuotation);

    }
    /**
     * 结束OA 分别调用不同esb
     * @return
     */
    public LossQuotation endOA(SimpleRequest simpleRequest){
        String approveOption = simpleRequest.get("approveOptions");
        LossQuotation lossQuotation;
        if (Objects.equals("A",approveOption)) {
            lossQuotation = goBack(simpleRequest);
        } else {
            lossQuotation = businessAudit(simpleRequest);
        }
        return lossQuotation;
    }
    /**
     * 完成询价
     * @return
     */
    @OutboxSubscriber(id="fn.lossQuotation.finishInquiry", name="询价完成调用定损")
    public LossQuotation finishInquiry(OutboxPayloadWrapper wrapper){
        JSONObject tempJson = JSONObject.parseObject(wrapper.getPayload());
        LossQuotation lossQuotation = lossQuotationRepository.findOne(tempJson.getString("sourceBusinessKey"));
        if (Objects.isNull(lossQuotation)) throw new RuntimeException("未找到对应的定损报价单,单号:"+tempJson.getString("sourceBusinessKey"));
        // if(!lossQuotation.getState().equals("toInquiry")) throw new RuntimeException("该定损报价单不处于转询价状态");
//        if(tempJson.getString("XJWCZT") != null && "1".equals(tempJson.getString("XJWCZT"))){
//            lossQuotation.setState("inquiryFinish");
//        }
        dealInquiryGoods(lossQuotation,tempJson);
        return lossQuotationRepository.saveAndFlush(lossQuotation);
    }

    /**
     * 添加修改询价过来商品价格
     *
     * 询价需要改变参数：
     * discountRate 折扣率
     * clerkPriceLimit 最低限价
     * shopOwnerPriceLimit 店长限价
     * csoPriceLimit 销售总监限价
     * basePrice 销售基准价
     *floorPrice  最低限价
     *managementFeeRate 管理费率
     * priceCostUnitInTax 含税成本单价
     * priceCostUnitInTax 含税成本单价
     * priceCostUnitExTax 不含税成本单价
     * primaryPriceUnit  原销售单价
     * priceUnit  销售单价
     * pftPriceUnit  优惠单价
     * @param lossQuotation
     * @param tempJson
     */
    private void dealInquiryGoods(LossQuotation lossQuotation, JSONObject tempJson) {
        JSONArray inquiryGoodsArray = tempJson.getJSONArray("PUR_SPXJDMX");
        inquiryGoodsArray.forEach(item ->{
            JSONObject itemTemp = (JSONObject)item;
            itemTemp.put("GSID",tempJson.getString("GSID"));
            itemTemp.put("PTID",tempJson.getString("PTID"));
        });
        //新增商品处理
        JSONArray extraInquiryGoodsArray = inquiryGoodsArray.stream().filter((item) -> {
            JSONObject itemExtra = (JSONObject) item;
            boolean flag = false; //默认非新增商品
            List list = lossQuotation.getLossQuotationItems().stream().filter(quotationItem -> {
                return quotationItem.getProduct().getId().equals(itemExtra.getString("SPID"));
            }).collect(Collectors.toList());
            if(list.size() == 0) flag = true;
            return flag;
        }).collect(Collectors.toCollection(JSONArray::new));

        if (extraInquiryGoodsArray.size() != 0) {
            extraInquiryGoodsArray.forEach((item) -> {  //只要商品一致，那么就退换询价信息
                JSONObject quiryJson = (JSONObject) item;
                LossQuotationItem lossQuotationItem;
                try {//获取到和新增商品匹配的定损明细商品
                    lossQuotationItem = lossQuotation.getLossQuotationItems().stream().filter(
                            (quotationItem) -> {
                                return (quotationItem.getProduct().getOrginID() != null)
                                        && Objects.equals(quotationItem.getProduct().getOrginID(), quiryJson.getString("YSPID"));
                            }).findFirst().orElse(null);
                } catch (Exception e) {
                    throw new RuntimeException("询价找来源商品失败");
                }
                if (Objects.nonNull(lossQuotationItem)) {
                    //把匹配到的商品封装到新的一个LossQuotationItem
                    LossQuotationItem lossQuotationItems = new LossQuotationItem();
                    ReflectUtil.copyAll(lossQuotationItem, lossQuotationItems, "id");
                    lossQuotationItems.setId(SpringManager.getBean(SequenceService.class).getId(LossQuotationItem.CONST_TABLE_NAME));
                    addNewInquiryParam(lossQuotation, lossQuotationItems, quiryJson);
                    lossQuotation.getLossQuotationItems().add(lossQuotationItems);
                }
            });
            //这样返回的只是原来getLossQuotationItems的东西，并不会成功加上newLssQuotationItems
            // newLssQuotationItems.addAll(lossQuotation.getLossQuotationItems());
            // lossQuotation.setLossQuotationItems(newLssQuotationItems);
        }
        List<Map> listMap= inquiryGoodsArray.stream().map((tempJson1)->{
            JSONObject item = (JSONObject)tempJson1;
            Product product = SpringManager.getBean(ProductRepository.class).findFirstByOrginID(item.getString("SPID"));
            item.put("uniqueIdentify",item.getString("XJDH") + item.getString("SPID"));
            return MapUtil.mapper(
                    "uniqueIdentify", item.getString("uniqueIdentify"),
                    "GSID", item.getString("GSID"),
                    "MDID", lossQuotation.getFixedLossDept().getId(),
                    "PLID", product.getClassify().getId(),
                    "SPID", product.getId(),
                    "PZID", product.getBrand().getQuality() == null ? null : product.getBrand().getQuality().getCode(),
                    "YYMS", lossQuotation.getFixedLossDept().getCompany().getParty().getCorporate().getOperation().getCode(),
                    "NYYMS", lossQuotation.getFixedLossDept().getCompany().getParty().getCorporate().getOperation().getId(),
                    "FNVIPJBID", lossQuotation.getCustomerExpand().getCustomerLevelId(),
                    "FNVIPSFID", lossQuotation.getCustomerExpand().getUserRoleId(),
                    "JLDW", item.getString("JLDW"),
                    "SYGSID", item.getString("PTID"),
                    "XYGSID", lossQuotation.getFixedLossDept().getCompany().getId(),
                    "XSDJ", item.getDouble("XSDJ"),
                    "XSXJ", item.getDouble("XSXJ"),
                    "XYGSCGJ", item.getDoubleValue("XYGSCGJ"),
                    "P001", item.getDoubleValue("CGDJ")
            );
        }).collect(Collectors.toCollection(ArrayList::new));
        JSONArray jgArray = serviceToForeign.getXJ51(listMap);
        for(int i = 0 ;i< inquiryGoodsArray.size();i++){
            boolean flag = true;
            JSONObject item1 = inquiryGoodsArray.getJSONObject(i);
            for(int j = 0; j < jgArray.size() ;j ++){
                JSONObject item2 = jgArray.getJSONObject(j);
                if(item1.getString("uniqueIdentify").equals(item2.getString("uniqueIdentify"))){
                    flag = false;
                    item1.putAll(item2);
                    item1.put("platformPriceCosInTax",item1.getDouble("CGDJ"));
                    item1.put("priceCostUnitExTax",item1.getDouble("XYGSCGJ"));
                    item1.put("priceCostUnitInTax",item1.getDouble("XYGSCGJ"));
                    item1.put("supplyChainManagement", (item1.getDouble("XYGSCGJ") == null || item2.getDouble("supplyRate") == null )? 0 : (item1.getDouble("XYGSCGJ") * item2.getDouble("supplyRate")));
                    item1.put("floorPrice",item1.getDouble("XSXJ"));
                    item1.put("referTax",item2.getDoubleValue("referTax") == 0 ? (1+item2.getDoubleValue("supplyRate")) * item1.getDouble("XYGSCGJ") : item2.getDoubleValue("referTax"));
                }
            }
            if(flag) throw new RuntimeException("询价未匹配到价格，请联系处理");
        }
        inquiryGoodsArray.forEach((item) -> {  //只要商品一致，那么就退换询价信息
            JSONObject quiryJson = (JSONObject) item;
            lossQuotation.getLossQuotationItems().forEach((lossQuotationItem) -> {
                if (lossQuotationItem.getProduct().getOrginID() == null)
                    throw new RuntimeException("该商品没有外部编码，商品编码" + lossQuotationItem.getProduct().getId());
                if (quiryJson.getString("SPID").equals(lossQuotationItem.getProduct().getOrginID())) {
                    addInquiryPrice(lossQuotationItem, quiryJson);
                }
            });
        });
    }

    /**
     * 询价新增商品解决各种对象转换
     * @param
     * @param quiryJson
     */
    private void addNewInquiryParam(LossQuotation lossQuotation,LossQuotationItem lossQuotationItem, JSONObject quiryJson) {
        Product product ;
        ProductUom uom ;
        Location location;
        try {
            product = productRepository.findFirstByOrginID(quiryJson.getString("SPID"));
        }catch (Exception e){
            long minutes = System.currentTimeMillis() / 1000 / 60 % 60;
            long synTime = minutes % 5;
            throw new RuntimeException(quiryJson.getString("SPID") + " 商品同步中，请等候 。。。。");
        }
        try {
            uom = productUomRepository.findAll(
                    JpaDsl.toCriteriaByEq("name",quiryJson.getString("JLDW"),"uomCategory.id",product.getUom().getUomCategory().getId(),"saleFirst",true)
            ).stream().findFirst().get();
        }catch (Exception e){
            throw new RuntimeException("新系统没有维护该扩展商品计量单位，计量单位"+ quiryJson.getString("JLDW"));
        }
        try {
            location = SpringManager.getBean(LocationService.class).findLocationByDept(lossQuotation.getFixedLossDept(),false);
        }catch (Exception e){
            throw new RuntimeException("仓库有误，仓库编码");
        }
        if(product.getProductGroup() == null ) throw new RuntimeException("商品组定义有误，商品编码" + product.getId());

        // lossQuotationItem.setServiceState(true);
        // lossQuotationItem.setAssessmentSituation(true);
        lossQuotationItem.setProduct(product);
        lossQuotationItem.setUom(uom);
        lossQuotationItem.setLocation(location);
        lossQuotationItem.setSaleQty(quiryJson.getDouble("XSSL"));
        lossQuotationItem.setProductRule(
                ((List) this.invoke("cm.consignmentRule.findAllByCategoryAndProvinceAndCity",
                        MapUtil.mapper("deptId", lossQuotation.getFixedLossDept().getId(),
                                "categoryId", product.getCategory().getId(), "brandId", product.getBrand().getId())
                )).size() != 0
        );
        lossQuotationItem.setLossQuotation(lossQuotation);
        ////取平台时和服务逻辑一模一样
        lossQuotationItem.setPlatform(fnCommunalService.getPlatform(false,true,lossQuotation.getFixedLossDept(),lossQuotationItem.getProduct()));
    }


    private Group getGroup(SimpleRequest request) {
        Post post = postRepository.findOne(request.getPostId());
        Group group = JpaDsl.getGroup(request);

        Group deptGroup = Tools.map(MapUtil.mapper(
                "operator", "or",
                "filters", new ArrayList(),
                "groups", new ArrayList()
        ), Group.class);

        deptGroup.addFilters(JpaDsl.toFilter(
                "dept1", "EQ",post.getDept(),
                "dept2", "EQ", post.getDept()
        ));
        group.addGroup(deptGroup);
        // lossQuotationRepository.findAll(JpaDsl.getGroup(group));
        return group;
    }


    /**
     * 更新服务方案的相关金额
     * @return
     */
    private void updateServicePlanMoney(LossQuotation lossQuotation){
        //得到不是自费的并且服务单号不为空的定损明细
        List<LossQuotationPlan> list = lossQuotation.getLossQuotationPlans().stream().filter(
                item -> !item.isPayYourself() && !StringUtils.isEmpty(item.getServicePlan())
        ).collect(toList());
        if (list.size() >0) {
            Group group = new Group();
            group.addFilters(JpaDsl.toFilter("sourceFrom","EQ",lossQuotation.getId(),"state","NE","termination"));
            List<ServicePlan> servicePlans =
                    SpringManager.getBean(ServicePlanRepository.class).findAll(JpaDsl.build(group,false));
            servicePlans.forEach(
                    servicePlan ->{
                        List<ServicePlanItem> set = servicePlan.getServicePlanItems(); // 服务明细
                        //判断该服务方案单得明细最大销售金额是否小于1,如果小于一 则代表是提前修车得需要回写价格
                        if (set.stream().max(Comparator.comparing(ServicePlanItem::getPftPriceUnit)).orElse(new ServicePlanItem()).getPftPriceUnit() <1 ){
                            //把服务方案商品对应的定损价格更新到服务方案上
                            for (ServicePlanItem item : set) {
                                for (LossQuotationPlan quotationPlan : list) {
                                    if (item.getProduct().getId().equals(quotationPlan.getProduct().getId())) {
                                        item.setPrimaryPriceUnit(quotationPlan.getFixedLossPrice());
                                        item.setPrimaryPriceUnitShow(quotationPlan.getFixedLossPrice());
                                        item.setPriceUnit(quotationPlan.getFixedLossPrice());
                                        item.setBasePrice(quotationPlan.getFixedLossPrice());
                                        item.setPftPriceUnit(quotationPlan.getFixedLossPrice());
                                        item.setClerkPriceLimit(quotationPlan.getFixedLossPrice());
                                        item.setShopOwnerPriceLimit(quotationPlan.getFixedLossPrice());
                                        item.setCsoPriceLimit(quotationPlan.getFixedLossPrice());
                                        item.setPriceCostUnitInTax(quotationPlan.getPriceCostUnitInTax());
                                        item.setPriceCostUnitExTax(quotationPlan.getPriceCostUnitExTax());
                                        item.setReferTax(quotationPlan.getReferTax());
                                        item.setSupplyChainManagement(quotationPlan.getSupplyChainManagement());
                                        item.setEstimatedCommission(quotationPlan.getEstimatedCommission());
                                    }
                                }
                            }
                            double claimAmount = servicePlan.getServicePlanItems()
                                    .stream().mapToDouble(
                                            item -> Arith.mul(item.getPftPriceUnit(), item.getSaleQty())

                                    ).sum();
                            servicePlan.setClaimAmount(claimAmount);
                            String id = servicePlan.getId();
                            if (id!=null)servicePlan = servicePlanRepository.saveAndFlush(servicePlan);
                            if (id==null)servicePlan = this.invoke("fn.service.createForInvoke", MapUtil.mapped(servicePlan));
                            if (id!=null)servicePlan = servicePlanceService.updateServe(servicePlan);
                            //塞进事务发件箱, 为了能查询到更新后得定损单数据
                            JSONObject object = new JSONObject();
                            object.put("id",servicePlan.getId());
                            object.put("sourceFrom",lossQuotation.getId());
                            outboxSubscriberService.commonSendRequest("local:LossQuotation.noticeAppSettleAccounts","Loss" + servicePlan.getId(),object);
                            // this.invoke("fn.service.confirmToApp",MapUtil.mapped(servicePlan));
                        }
                    }
            );
        }
    }

    /**
     * 定损查询询价信息
     * @param simpleRequest
     * @return
     */
    public JSONObject qryXJDetailForDS(SimpleRequest simpleRequest){
        JSONObject json = simpleRequest.getJO();
        String id = json.getString("id");
        if(id == null || "".equals(id.trim())) return null;
        LossQuotation lossQuotation = lossQuotationRepository.findOne(id);
        if(lossQuotation == null) throw new RuntimeException("miss：cannot find LossQuotation ,id:" + id);
        // //查找该服务方案单所有的询价信息
        // JSONObject condition = new JSONObject();
        // condition.put("LYDJHM", id);
        // JSONObject obj = piManager.synErp("mdmPjmcService.findSPXJDFromSource", condition);
        // JSONArray resultArray = JSONArray.parseArray(obj.getString("obj"));

        //车辆信息
        FnCustomerExpand fnCustomerExpand = lossQuotation.getCustomerExpand();
        //根据配件名称分组，询价过的商品
        Map map = lossQuotation.getLossQuotationItems().stream().filter((item)->{
            return Optional.ofNullable(item.getOldInquiryNumber()).isPresent();
        }).collect(Collectors.groupingBy((x)->{
            return x.getProduct().getCategory().getId();
        }));
        //构建json
        JSONObject reJson = new JSONObject();
        reJson.put("carLicense",fnCustomerExpand == null ? null : fnCustomerExpand.getCarLicense());
        reJson.put("modelName",fnCustomerExpand == null ? null : fnCustomerExpand.getCarModelLabel());

        JSONArray array = new JSONArray();
        map.forEach((k,v)->{
            HashSet<LossQuotationItem> lossQuotationItems = new HashSet<LossQuotationItem>((Collection<? extends LossQuotationItem>) v);
            JSONObject tempJson = new JSONObject();
            tempJson.put("categoryName",lossQuotationItems.stream().findFirst().orElse(new LossQuotationItem()).getCategory().getName());
            tempJson.put("categoryId",lossQuotationItems.stream().findFirst().orElse(new LossQuotationItem()).getCategory().getId());
            tempJson.put("inquryDetail","");
            JSONArray itemArray = lossQuotationItems.stream().map((lossQuotationItem)->{
                JSONObject tempJson1 = new JSONObject();
                tempJson1.put("name",lossQuotationItem.getProduct().getName());
                tempJson1.put("goodsGetDetail","");
                tempJson1.put("remark",lossQuotationItem.getRemarks());
                tempJson1.put("price",lossQuotationItem.getSalesAmount());
                tempJson1.put("cusRemark","");
                tempJson1.put("lossQuotationItemId", lossQuotationItem.getId());
                tempJson1.put("id",lossQuotationItem.getProduct().getId());
                tempJson1.put("inquirySelectFlag",lossQuotationItem.getInquirySelectFlag());
                //该商品对应的询价信息
                JSONObject condition = new JSONObject();
                condition.put("XJDH",lossQuotationItem.getOldInquiryNumber());
                condition.put("SPID",lossQuotationItem.getProduct().getId());
                //该商品对应的询价信息
                getOldInquiryInfo(condition,tempJson1);
                return tempJson1;
            }).collect(Collectors.toCollection(JSONArray::new));
            tempJson.put("item",itemArray);
            array.add(tempJson);
        });
        handleSupplierCode(array);
        reJson.put("item",array);
        return reJson;
    }

    public void getOldInquiryInfo(JSONObject condition,JSONObject result) {
        JSONObject obj = SpringManager.getBean(PiManager.class).synErp("mdmPjmcService.findSPXJDFromSource", condition);
        JSONArray dataArray = JSONArray.parseArray(obj.getString("obj"));
        if(dataArray.size() == 0) return ;
        JSONObject information = dataArray.getJSONObject(0);
        result.put("remake",information.getString("ZY"));
        result.put("cusRemark",information.getString("CGYJ"));
        result.put("ADDRESS", "");
        result.put("goodsSupply",information.getString("HYZT"));
        if(!StringUtils.isEmpty(information.getString("YJDHSC"))){
            result.put("purchaseInformation", "下单后 " + information.get("YJDHSC") + " 送达" + information.get("ZDMC"));
        }
        result.put("purchasingGroupId", information.get("CGZID"));
        result.put("purchasingGroupName", information.get("CGZMC"));
        result.put("siteId", information.get("ZDID"));
        result.put("siteName", information.get("ZDMC"));
        result.put("siteShippingAddress", information.get("ZZZSHDZ"));
        result.put("supplierRemark", information.getString("GYSBZ"));
        result.put("supplier", information.getString("GSYID"));
        result.put("quality", information.getString("PZMC"));
        result.put("artwork", information.getString("YLTP"));
        result.put("newImage", information.getString("XZTP"));
        //添加下游公司采购单价，下游公司销售单价
        result.put("ppUnitX", information.getDoubleValue("XYGSCGJ"));  //purchaseUnit
        result.put("spUnitX", information.getDoubleValue("XYGSXSJ")); //saleUnit
    }

    /**
     * 批量处理供应商编码
     * @param array
     */

    public void handleSupplierCode(JSONArray array) {
        //把供应商编码做处理
        JSONObject cacheObject = new JSONObject();
        //如果缓存对象中存在该供应商编码得值,则将该值赋值给供应商 没有则添加进去
        array.forEach(
                item -> {
                    JSONObject object = (JSONObject) item;
                    object.getJSONArray("item").forEach(
                            itemData -> {
                                JSONObject itemObject = (JSONObject) itemData;
                                if (cacheObject.containsKey(itemObject.getString("supplier"))){
                                    itemObject.put("supplier",cacheObject.getString(itemObject.getString("supplier")));
                                }else {
                                    int random=(int)(Math.random()*900)+100;
                                    cacheObject.put(itemObject.getString("supplier"), random);
                                    itemObject.put("supplier", random);
                                }
                            }
                    );

                }
        );
    }

    @OutboxSubscriber(id="local:LossQuotation.noticeAppSettleAccounts", name="定损通知app结算")
    private void noticeAppSettleAccounts(OutboxPayloadWrapper outboxPayloadWrapper){
        //再查一遍服务方案的最新数据
        JSONObject object = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        ServicePlan servicePlan = SpringManager.getBean(ServicePlanRepository.class).findOne(object.getString("id"));
        if (servicePlan != null && Objects.equals("qualityTest",servicePlan.getState())) {
            OutboxPayloadWrapper wrapper = new OutboxPayloadWrapper();
            wrapper.setSubscriber("servicePlan.server.confirmToApp");
            wrapper.setAggregateId("LossDeliver:" + servicePlan.getId());
            wrapper.setPayload(JSON.toJSONString(MapUtil.mapper("id",servicePlan.getId(),"state",servicePlan.getState())));
            SpringManager.getBean(OutboxEventService.class).sendSaveEvent(wrapper);
        }
    }

    @OutboxSubscriber(id="local:LossQuotation.writeEstimatedCommission", name="定损写预估提成")
    private void writeEstimatedCommission(OutboxPayloadWrapper outboxPayloadWrapper){
        //再查一遍服务方案的最新数据
        JSONObject object = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        LossQuotation lossQuotation = lossQuotationRepository.findOne(object.getString("id"));
        String COMPANY_ID = lossQuotation.getCompany().getId();
        String OPERATION = lossQuotation.getCompany().getParty().getCorporate().getOperation().getDescription();
        lossQuotation.getLossQuotationPlans().forEach(
                item ->{
                    JSONObject jsonObject = new JSONObject();
                    Product product = item.getProduct();
                    jsonObject.put("PRODUCT_ID",product.getId());
                    jsonObject.put("COMPANY_ID",COMPANY_ID);
                    jsonObject.put("CLASSIFY_ID",product.getClassify().getId());
                    jsonObject.put("SERVE_TYPE_ID",item.getServeType().getId());
                    jsonObject.put("BRAND_ID",product.getBrand().getId());
                    jsonObject.put("ORDER_TYPE",lossQuotation.getInnerBusinessType());
                    jsonObject.put("SOURCE_BUSINESS_TYPE_NAME","定损报价单");
                    jsonObject.put("PROFIT_AMT",item.getReferTax());
                    jsonObject.put("OPERATION",OPERATION);
                    jsonObject.put("SALE_AMT",item.getFixedLossPrice());
                    jsonObject.put("DISCOUNT_AMOUNT",0);
                    jsonObject.put("LOCK_PRICE",item.getFloorPrice());
                    jsonObject.put("SALE_QTY",1);
                    jsonObject.put("YXSDJ",item.getMinFixedLossAmount());
                    jsonObject.put("HBDK_AMT",0);
                    jsonObject.put("NKDK_AMT",0);
                    jsonObject.put("FXDK_AMT",0);
                    jsonObject.put("DSBJ",1);
                    jsonObject.put("SYS_RQ",new Date());
                    jsonObject.put("conditionStrategyId","TC_YSXSTC_SK");
                    try {
                        //获取预估提成单价 并回写到定损确认方案上
                        Object obj = this.invoke("condition.execConditionStrategyNoSession",jsonObject);
                        String  str = obj.toString();
                        JSONObject data = JSONObject.parseObject(str);
                        Double estimatedCommission =  data.getDouble("TCJE") == null ? 0 : data.getDouble("TCJE");
                        item.setEstimatedCommission(estimatedCommission);
                    }catch (Exception e){
                        throw new RuntimeException("计算预估提成失败：" + e.getMessage());
                    }

                }
        );
        lossQuotationRepository.saveAndFlush(lossQuotation);
    }

    /**
     * 处理理赔类型
     * @param lossQuotation
     */
    public void handleBusinessAttributeValue(LossQuotation lossQuotation){

        CarAccident carAccident = carAccidentRepository.findOne(lossQuotation.getCarAccident());
        InsuranceCompany insuranceCompany = carAccident.getInsuranceCompany();  //保险公司信息
        //施工门店信息(省市)
        Area province = lossQuotation.getFixedLossDept().getCompany().getParty().getCorporate().getRegProvince();
        Area city = lossQuotation.getFixedLossDept().getCompany().getParty().getCorporate().getRegCity();
        InsuranceCompanyDetail byInsuranceCompanyAndProvinceAndCity = SpringManager.getBean(InsuranceCompanyDetailRepository.class).findByInsuranceCompanyAndProvinceAndCity
                (insuranceCompany, province, city);
    }

    /**
     * 将接车类型明细转换为字符串存储
     * @param map 业务model 对象
     */
    public String setGetCarType(Map<String, Object> map) {
        String getCarType = "";
        if (Objects.equals("LossQuotation",map.get("innerBusinessType"))){
            LossQuotation lossQuotation = MapUtil.getO(map, LossQuotation.class);
            if (Objects.nonNull(lossQuotation.getTypeBusinesses()) && lossQuotation.getTypeBusinesses().size() >0) {
                getCarType = lossQuotation.getTypeBusinesses().stream()
                        .map(item ->  item.getPickUpType().getDescription()).collect(Collectors.joining(","));
            }
        }else if (Objects.equals("ServicePlan", map.get("innerBusinessType"))){
            ServicePlan servicePlan = MapUtil.getO(map, ServicePlan.class);
            if (Objects.nonNull(servicePlan.getPickUpTypeS()) && (servicePlan.getPickUpTypeS().size() > 0)) {
                getCarType = servicePlan.getPickUpTypeS().stream()
                        .map(item ->  item.getPickUpType().getDescription()).collect(Collectors.joining(","));
            }
        }
        return getCarType;
    }

    /**
     * 暂停定损
     */
    public LossQuotation suspendVehicleDamage (SimpleRequest request)  {
        checkData(request);
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        if (StringUtils.isEmpty(lossQuotation.getSuspendReason()) && StringUtils.isEmpty(lossQuotation.getRemark())) {
            throw new RuntimeException("暂定定损必须填写原因或备注!!!");
        }
        List<LossQuotationRecord> list = new ArrayList<>(lossQuotation.getLossQuotationRecords());
        LossQuotationRecord record = new LossQuotationRecord();
        record.setLossQuotation(lossQuotation);
        record.setOperate("暂停定损");
        record.setRemark(StringUtils.isEmpty(lossQuotation.getSuspendReason()) ? lossQuotation.getRemark() : lossQuotation.getSuspendReason());
        record.setOperateDate(new Date());
        record.setOperateUid(request.getPerson());
        list.add(record);
        lossQuotation.getLossQuotationRecords().clear();
        lossQuotation.setLossQuotationRecords(list);

        lossQuotation.setState("suspend");
        return lossQuotationRepository.saveAndFlush(lossQuotation);

    }

    /**
     * 开始定损
     */
    public LossQuotation startVehicleDamage (SimpleRequest request) {
        checkData(request);
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        List<LossQuotationRecord> list = new ArrayList<>(lossQuotation.getLossQuotationRecords());
        LossQuotationRecord record = new LossQuotationRecord();
        record.setLossQuotation(lossQuotation);
        record.setOperate("开始定损");
        record.setOperateDate(new Date());
        record.setOperateUid(request.getPerson());
        list.add(record);
        lossQuotation.getLossQuotationRecords().clear();
        lossQuotation.setLossQuotationRecords(list);
        lossQuotation.setState("techAudit");
        return lossQuotationRepository.saveAndFlush(lossQuotation);

    }

    /**
     * 记录修改追加返还率的历史记录
     * @param lossQuotation 定损报价单
     * @param request 请求信息
     */
    private void recordEditHistory (LossQuotation lossQuotation,SimpleRequest request) {
        //判断 追加返还率是否被修改
        double accessoriesReturnRatio = lossQuotation.getReturnRatioAccessories();
        double serviceReturnRatio = lossQuotation.getServiceReturnRatio();
        double oldServiceRatio = 0;
        double oldAccessoriesRatio = 0;
        if (!StringUtils.isEmpty(lossQuotation.getId())) {
            LossQuotation oldQuotation = lossQuotationRepository.findOne(lossQuotation.getId());
            oldServiceRatio = oldQuotation.getServiceReturnRatio();
            oldAccessoriesRatio = oldQuotation.getReturnRatioAccessories();
        }
        if (accessoriesReturnRatio != oldAccessoriesRatio || serviceReturnRatio != oldServiceRatio) {
            List<LossQuotationRecord> list = new ArrayList<>(lossQuotation.getLossQuotationRecords());
            LossQuotationRecord record = new LossQuotationRecord();
            record.setLossQuotation(lossQuotation);
            record.setOperate("修改追加返还比率");
            record.setOperateDate(new Date());
            record.setOperateUid(request.getPerson());
            record.setRemark("工时追加返还率: "+ oldServiceRatio +"->" +serviceReturnRatio +";配件追加返还率: " + oldAccessoriesRatio +"->" +accessoriesReturnRatio);
            list.add(record);
            lossQuotation.getLossQuotationRecords().clear();
            lossQuotation.setLossQuotationRecords(list);
        }
    }
    /**
     * 获取定损业务费率
     * @param lossQuotation 定损报价单
     * A004	代码单信息费率
     * A005	非代码单信息费率
     * A006	推修信息费率
     */
    private void parsingReturnRatio (LossQuotation lossQuotation) {
        JSONObject lossQuotationRule =
                SpringManager.getBean(RetailOrderFnExpenseOrderService.class)
                        .getConditionRule(lossQuotation.getFixedLossDept(), lossQuotation.getInsuranceCompany(), lossQuotation.getGetCarDept().getCompany());
        CarAccident carAccident = carAccidentRepository.findOne(lossQuotation.getCarAccident());
        Enumeration caseType = carAccident.getCaseType();
        String  id = caseType.getId();
        double returnRatio;
        //案件类型 001493 非车险会员推送 ,001494 门店接车合作保险 ,001492 代堪到店 , 001490 门店接车非合作保险 , 001491 车险会员报案
        switch (id) {
            case "001490":
            case "001494":
                returnRatio = lossQuotationRule.getDoubleValue("A005");
                break;
            case "001491":
                returnRatio = lossQuotationRule.getDoubleValue("A004");
                break;
            case "001493":
            case "001492":
                returnRatio = lossQuotationRule.getDoubleValue("A006");
                break;
            default:
                returnRatio = 0;
        }
        lossQuotation.setReturnRatio(returnRatio*100);
    }

    public  List<LossQuotation> queryUnsettledForLossQuotation (SimpleRequest request) {
        JSONObject param = request.getJO();
        return lossQuotationRepository.findByCarAccident(param.getString("ID"));
    }

    /**
     * 询价池导入方案
     * @param request
     * @return
     */
    public JSONArray getInquiryPoolItem(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONArray inquiryGoodsArray = jo.getJSONArray("PUR_SPXJDMX");
        if (jo.getString("id")==null&&jo.getString("orderTypeTemp")==null)throw new RuntimeException("单号不能为空");

        JSONArray result = new JSONArray();
        result = translateField(inquiryGoodsArray, jo);

        return result;
    }

    public JSONArray translateField(JSONArray inquiryGoodsArray,JSONObject lossQuotation){
        if (lossQuotation.getJSONObject("orderType")==null)throw new RuntimeException("缺失数据类型,请刷新重试");
        BusinessAttributeValue attributeValue = SpringManager.getBean(BusinessAttributeValueRepository.class).findOne(lossQuotation.getJSONObject("orderType").getString("id"));
        JSONObject customer = lossQuotation.getJSONObject("customer");
        String getCarDeptId = lossQuotation.getJSONObject("getCarDept").getString("id");
        String fixedLossDeptId = lossQuotation.getJSONObject("fixedLossDept").getString("id");
        JSONArray jgArray = new JSONArray();
        inquiryGoodsArray.forEach(item ->{
            JSONObject itemTemp = (JSONObject)item;
            itemTemp.put("GSID",itemTemp.getString("GSID"));
            itemTemp.put("PTID",itemTemp.getString("PTID"));
        });

        Product newProduct = productRepository.findOne(inquiryGoodsArray.getJSONObject(0).getString("SPID"));
        List<Map> listMap= inquiryGoodsArray.stream().map((tempJson1)->{
            //委托定 询价门店需要取接车门店
            Dept fixedLossDept  = new Dept();
            if (Objects.equals("B",attributeValue.getCode())) {
                fixedLossDept = deptRepository.findOne(getCarDeptId);
            }else {
                fixedLossDept = deptRepository.findOne(fixedLossDeptId);
            }
            JSONObject item = (JSONObject)tempJson1;
            Product product = SpringManager.getBean(ProductRepository.class).findFirstByOrginID(item.getString("SPID"));

            if (product==null)throw new RuntimeException("查询不到商品：ID【"+item.getString("SPID")+"】");
            Classify classify = product.getClassify();
            if(classify==null)throw new RuntimeException("当前商品:"+product.getName()+",分类不存在");
            item.put("uniqueIdentify",item.getString("XJDH") + item.getString("SPID"));
            return MapUtil.mapper(
                    "uniqueIdentify", item.getString("uniqueIdentify"),
                    "GSID", fixedLossDept.getCompany().getId(),
                    "MDID", fixedLossDept.getId(),
                    "PLID", classify.getId(),
                    "SPID", product.getId(),
                    "PZID", product.getBrand().getQuality() == null ? null : product.getBrand().getQuality().getCode(),
                    "YYMS", fixedLossDept.getCompany().getParty().getCorporate().getOperation().getCode(),
                    "NYYMS", fixedLossDept.getCompany().getParty().getCorporate().getOperation().getId(),
                    "FNVIPJBID", customer.getString("level"),
                    "FNVIPSFID", customer.getString("userRole"),
                    "JRS", customer.getString("vendorCode"),
                    "JLDW", item.getString("JLDW"),
                    "SYGSID", item.getString("PTID"),
                    "XYGSID", fixedLossDept.getCompany().getId(),
                    "XSDJ", item.getDouble("XSDJ"),
                    "XSXJ", item.getDouble("XSXJ"),
                    "XYGSCGJ", item.getDoubleValue("XYGSCGJ"),
                    "P001", item.getDoubleValue("CGDJ")
            );
        }).collect(Collectors.toCollection(ArrayList::new));
        jgArray = serviceToForeign.getXJ51(listMap);
        for(int i = 0 ;i< inquiryGoodsArray.size();i++){
            boolean flag = true;
            JSONObject item1 = inquiryGoodsArray.getJSONObject(i);
            for(int j = 0; j < jgArray.size() ;j ++){
                JSONObject item2 = jgArray.getJSONObject(j);
                if(item1.getString("uniqueIdentify").equals(item2.getString("uniqueIdentify"))){
                    flag = false;
                    item1.putAll(item2);
                    Double xygscgj = item1.getDouble("XYGSCGJ")==null? item1.getDouble("CGDJ"):item1.getDouble("XYGSCGJ");
                    item1.put("platformPriceCosInTax",item1.getDouble("CGDJ"));
                    item1.put("priceCostUnitExTax", xygscgj);
                    item1.put("priceCostUnitInTax", xygscgj);
                    item1.put("supplyChainManagement", (xygscgj == null || item2.getDouble("supplyRate") == null )? 0 : (xygscgj ));
                    item1.put("floorPrice",item1.getDouble("XSXJ"));
                    item1.put("referTax",item2.getDoubleValue("referTax") == 0 ? (1+item2.getDoubleValue("supplyRate")) * xygscgj : item2.getDoubleValue("referTax"));
                }
            }
            if(flag) throw new RuntimeException("询价未匹配到价格，请联系处理");
        }
        //库区额外信息
        JSONArray resultList = new JSONArray();
        List inquiryPool = getInquiryPool(lossQuotation);
        inquiryGoodsArray.stream().forEach((item) -> {
            //委托定 询价门店需要取接车门店
            Dept fixedLossDept  = new Dept();
            if (Objects.equals("B",attributeValue.getCode())) {
                fixedLossDept = deptRepository.findOne(getCarDeptId);
            }else {
                fixedLossDept = deptRepository.findOne(fixedLossDeptId);
            }
            JSONObject quiryJson = (JSONObject) item;
            JSONObject resultJson = new JSONObject();
            resultJson.put("company", fixedLossDept.getCompany());
            PartyRole partyRole = SpringManager.getBean(PartyRoleService.class).findOne(quiryJson.getString("PTID"),"Company");
            resultJson.put("platform", partyRole);
            //商品
            resultJson.put("product", JSONObject.parseObject("{" +
                    "\"id\":\""+quiryJson.getString("SPID")+"\"," +
                    "\"name\":\""+quiryJson.getString("SPMC")+"\"}" ));
            resultJson.put("category", JSONObject.parseObject("{" +
                    "\"id\":\""+quiryJson.getString("PJMCID")+"\"," +
                    "\"name\":\""+quiryJson.getString("PJMC")+"\"}" ));
            List<ProductUom> productUomList = productUomRepository.findAll(
                    JpaDsl.toCriteriaByEq("uomCategory.id", quiryJson.getString("SPID"), "name", quiryJson.getString("JLDW")));
            if(productUomList == null||productUomList.size()==0)throw new RuntimeException("该商品未定义计量单位，计量单位"+ quiryJson.getString("JLDW") + ",对应商品：" + quiryJson.getString("SPID"));
            if (productUomList != null && productUomList.size() != 0) {
                resultJson.put("uom", productUomList.get(0));
            }
            //配件为工时 时 评估类型默认为工时,否则为配件
            if ("20".equals(quiryJson.getString("SPZID"))){
                resultJson.put("evaluationType",MapUtil.mapper("id","LossQuotationItem.evaluationType.A","name","工时"));
            }else{
                resultJson.put("evaluationType",MapUtil.mapper("id","LossQuotationItem.evaluationType.B","name","配件"));
            }
            //价格
            resultJson.put("uniqueValue", quiryJson.getString("WYZ"));
//            resultJson.put("addInfo", MapUtil.mapper("transfer",quiryJson.getString("ZDMC")));
            resultJson.put("minimumPrice", quiryJson.getDoubleValue("referTax") > 0?quiryJson.getDoubleValue("referTax") : quiryJson.getDouble("floorPrice"));
            resultJson.put("primaryPriceUnit",quiryJson.getDouble("primaryPriceUnit"));
            resultJson.put("salePrice",quiryJson.getDouble("priceUnit"));
            resultJson.put("pftPriceUnit",quiryJson.getDouble("priceUnit"));
            resultJson.put("managementFeeRate",quiryJson.getDouble("managementFeeRate"));
            resultJson.put("floorPrice",quiryJson.getDouble("floorPrice"));
            resultJson.put("basePrice",quiryJson.getDouble("basePrice"));
            resultJson.put("discountRate", (quiryJson.getDouble("pftPriceUnit") >0 && quiryJson.getDouble("primaryPriceUnit") >0)?
                    Arith.div(quiryJson.getDouble("pftPriceUnit"),quiryJson.getDouble("primaryPriceUnit"),4) :0);
            resultJson.put("priceCostUnitInTax",quiryJson.getDouble("priceCostUnitInTax"));
            resultJson.put("priceCostUnitExTax", quiryJson.getDouble("priceCostUnitExTax"));
            resultJson.put("platformPriceCosInTax",quiryJson.getDouble("platformPriceCosInTax")); //平台成本价
            Product product = productRepository.findOne(quiryJson.getString("SPID"));
            if (Objects.isNull(product)) {
                throw new RuntimeException("系统中未找到该商品数据,编码: " + quiryJson.getString("SPID"));
            }
            double fee = SpringManager.getBean(FeeRateService.class).getSupplyChainManagementFee(fixedLossDept.getCompany().getId(), product.getClassify().getId(), "");

            resultJson.put("supplyChainManagement",quiryJson.getDouble("supplyChainManagement") * fee); //供应链管理费
            resultJson.put("innerBusinessKey",quiryJson.getString("SPID"));
            resultJson.put("inquirySelectFlag",1);
            resultJson.put("saleQty",1);
            resultJson.put("salesAmount", quiryJson.getDouble("priceUnit"));
            resultJson.put("referTax", quiryJson.getDoubleValue("pftPriceUnit") <= 0 ? 0 : quiryJson.getDoubleValue("referTax"));
            //前端要求需要返回的
            if(quiryJson.getString("HYZT") != null && "0".equals(quiryJson.getString("HYZT").trim())){
                resultJson.put("serviceState", false);
            }else {resultJson.put("serviceState", true);}
            resultJson.put("innerBusinessKey", quiryJson.getString("SPID"));
            resultJson.put("inquirySelectFlag", 1);
            //单独返回默认销售数量
            resultJson.put("saleQty", 1);
            //询价单号
            Double yjdhsc = quiryJson.getDouble("YJDHSC");
            if (yjdhsc!=null){
                Double yjdhts = yjdhsc/24;
                resultJson.put("expectedArrivalTimeTemp", yjdhts);
                resultJson.put("expectedArrivalTime", yjdhsc);
            }
            resultJson.put("oldInquiryNumber", quiryJson.getString("XJDH"));
            resultJson.put("tagMapAddress", quiryJson.getString("tagMapAddress"));
            resultJson.put("partCode", quiryJson.getString("partCode"));
            resultJson.put("partName", quiryJson.getString("partName"));
            resultJson.put("originalInquiryProduct", quiryJson.getJSONObject("originalInquiryProduct"));
            resultJson.put("inquiryGooodsState", quiryJson.getInteger("HYZT"));

            resultJson.put("supplierRemarks", quiryJson.getString("supplierRemarks"));
            resultJson.put("purchaseRemarks", quiryJson.getString("purchaseInformation"));

            boolean productRule = ((List) this.invoke("cm.consignmentRule.findAllByCategoryAndProvinceAndCity",
                    MapUtil.mapper("deptId", fixedLossDept.getId(),
                            "categoryId", quiryJson.getString("PJMCID"), "brandId", quiryJson.getString("PPID"))
            )).size() != 0;
            resultJson.put("productRule", productRule);
            servicePlanceService.checkNowOffice(resultJson, newProduct, fixedLossDept,inquiryPool , quiryJson.getDouble("priceUnit"),productRule);//报价信息

            Location location;
            try {
                location = SpringManager.getBean(LocationService.class).findLocationByDept(fixedLossDept, productRule);
                if (productRule) {
                    if (location == null) throw new RuntimeException("门店没有设置带安虚拟库，门店名称：" + fixedLossDept.getName());
                } else {
                    if (location == null) throw new RuntimeException("未找到门店对应的仓库" + fixedLossDept.getName());
                }
                resultJson.put("location", location);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }

            Map qryQualityInfo = this.invoke("fn.fnCommunalService.qryQualityInfo", MapUtil.mapper("SPID", quiryJson.getString("SPID"), "PLID", quiryJson.getString("PLID"), "PPID", quiryJson.getString("PPID")));
            if (qryQualityInfo != null) {
                resultJson.put("qualityWarranty", qryQualityInfo.get("qualityWarranty"));
                resultJson.put("qualityMileage", qryQualityInfo.get("qualityMileage"));
            }
            resultJson.put("serveType", newProduct.queryServeType());
            resultJson.put("logisticsMode", quiryJson.get("logisticsMode"));
            if (!StringUtils.isEmpty(quiryJson.get("logisticsMode"))) {
                resultJson.put("carrierId", quiryJson.getJSONObject("logisticsMode").getString("id"));
                resultJson.put("carrierName", quiryJson.getJSONObject("logisticsMode").getString("name"));
            }
            resultList.add(resultJson);

        });

        return resultList;

    }

    public JSONObject checkToInquiryItems(SimpleRequest request){
        JSONObject jo = request.getJO();
        String id = jo.getString("id");
        LossQuotation lossQuotation = lossQuotationRepository.findOne(id);
        JSONObject result = new JSONObject();
        //需要排除不服务的商品去查询是否询价
        Map inquiryPool = this.invoke("commodityInquiry.order.getInquiryPool", new JSONObject(MapUtil.mapped(lossQuotation,"lossQuotationItems","lossQuotationPlans")));
        List items = (List) inquiryPool.get("item");
        List list = lossQuotation.getLossQuotationItems()
                .stream()
                .filter(lossQuotationItem -> {
                    if ("20".equals(lossQuotationItem.getProduct().getProductGroup().getId()) && !lossQuotationItem.isProductRule())
                        return false;
                    return true;
                }).sorted(Comparator.comparing(LossQuotationItem::getPartCode, Comparator.nullsLast(String::compareTo))).map(lossQuotationItem -> {
                    return webNeedValue(items, lossQuotationItem, lossQuotation);
                }).collect(Collectors.toList());
        result.put("node", list);

        request.setData(MapUtil.mapper("carLicense", lossQuotation.getCustomerExpand().getCarLicense(), "vendorCode", lossQuotation.getCustomerExpand().getVendorCode()));
        String pictures = getBean(FnAppCustomerService.class).getPictures(request);
        result.put("pictures", pictures);
        return result;
    }

    public List filterNotInquiryItem(List items,LossQuotation lossQuotation){
        return lossQuotation.getLossQuotationItems().stream().sorted(Comparator.comparing(a ->a.getPartCode(),Comparator.nullsLast(String::compareTo))).filter(lossQuotationItem -> {
            if("20".equals(lossQuotationItem.getProduct().getProductGroup().getId()) && !lossQuotationItem.isProductRule())return false;
            return true;
        }).collect(Collectors.toList());
    }

    public JSONObject webNeedValue(List items,LossQuotationItem lossQuotationItem,LossQuotation lossQuotation){
        JSONObject jsonObject = new JSONObject();
        String oem = lossQuotationItem.getPartCode();

        jsonObject.put("partCode",oem);
        jsonObject.put("smartEpcPartName", lossQuotationItem.getPartName());
        jsonObject.put("category",lossQuotationItem.getProduct().getCategory());
        jsonObject.put("id",lossQuotationItem.getId());
        jsonObject.put("lossQuotationId",lossQuotationItem.getLossQuotation().getId());
        jsonObject.put("product",lossQuotationItem.getProduct());
        jsonObject.put("saleQty",lossQuotationItem.getSaleQty());
        jsonObject.put("primaryPriceUnitShow",lossQuotationItem.getSalePrice());
        jsonObject.put("referTax",lossQuotationItem.getReferTax());
        jsonObject.put("priceCostUnitInTax",lossQuotationItem.getPriceCostUnitInTax());
        jsonObject.put("supplyChainManagement",lossQuotationItem.getSupplyChainManagement());
        jsonObject.put("epcPicture",lossQuotationItem.getMapAddress());
        jsonObject.put("vin",lossQuotation.getCustomerExpand().getVin());
        jsonObject.put("price",lossQuotationItem.getFourSPrice());
        jsonObject.put("productId",lossQuotationItem.getProduct().getId());
        jsonObject.put("productName",lossQuotationItem.getProduct().getName());
        if ("000609,013951".contains(lossQuotationItem.getProduct().getCategory().getId())){
            jsonObject.put("note",lossQuotationItem.getProduct().getName());
        }
        //轮胎规格
        if ("000609".equals(lossQuotationItem.getProduct().getCategory().getId())){
            jsonObject.put("oem", lossQuotationItem.getProduct().getModel());
        }
        if (Objects.nonNull(lossQuotationItem.getProduct().getClassify()) &&
                (lossQuotationItem.getProduct().getClassify().getId().contains("M0102"))
                || lossQuotationItem.isProductRule()){
            jsonObject.put("productRule",true);
        }

        jsonObject = servicePlanceService.checkNowOffice(jsonObject, lossQuotationItem.getProduct(), lossQuotation.getFixedLossDept(), items, lossQuotationItem.getSaleQty(),lossQuotationItem.isProductRule());
        return jsonObject;
    }

    public LossQuotation productToInquiry(SimpleRequest request){
        JSONArray lossQuotationItems = request.getJO().getJSONArray("lossQuotationItems");
        String itemid = lossQuotationItems.getJSONObject(0).getString("id");
        LossQuotationItem item1 = lossQuotationItemRepository.findOne(itemid);
        LossQuotation lossQuotation = item1.getLossQuotation();
        lossQuotation.getLossQuotationItems().stream().forEach(lossQuotationItem -> {
            boolean falg = false;//是否存在转询价列表
            for (Object quotationItem : lossQuotationItems) {
                JSONObject itemJson = (JSONObject) quotationItem;
                if (itemJson.getString("id").equals(lossQuotationItem.getId())){
                    falg = true;
                    if (!itemJson.getBoolean("checkData")){
                        lossQuotationItem.setNeedInquiry(false);
                    }
                }
            }
            if (!falg){
                lossQuotationItem.setNeedInquiry(false);
            }
        });

        return  this.invoke("fn.lossQuotation.toInquiry",MapUtil.mapped(lossQuotation));

    }

    public LossQuotation insertOffice(SimpleRequest request){
        LossQuotation lossQuotation = request.getO(LossQuotation.class);
        if (lossQuotation.getFixedLossDept()==null)return null;
        return (LossQuotation) insertCommonData(lossQuotation);
    }






    /**
     * 检查定损单接车门店是否有资格委托定损
     * @param request
     * @return
     */
    public String checkStoreQuota(SimpleRequest request) {
        JSONObject param = request.getJO();
        String carAccidentId = param.getString("carAccident");
        if (Objects.isNull(carAccidentId)) {
            throw new RuntimeException("车险报案单号不能为空!!!");
        }
        CarAccident carAccident = carAccidentRepository.findOne(carAccidentId);
        if (Objects.isNull(carAccident)) {
            throw new RuntimeException("系统中未存在该报案单号,单号: " + carAccidentId );
        }
        JSONObject result = SpringManager.getBean(CarAccidentService.class).getReimbursementRatio(carAccident.getDept().getCompany());
        if (!Objects.isNull(result.getString("sys_break")) && Objects.equals("1",result.getString("sys_break"))) {
            throw new RuntimeException("门店未签署委托定损协议,不能选择委托定损!!!");
        }
        return carAccidentId;
    }

    /**
     * 获取定损分成率
     * @param lossQuotation 定损报价单
     */
    private void parsingDividendRatio (LossQuotation lossQuotation) {
        JSONObject result = getCarDamageRate(lossQuotation);
        Enumeration caseType = lossQuotation.getCaseType();
        String  id = caseType.getId();
        double dividendStore,dividendBase,dividendPlatform ;
        //案件类型 001493 非车险会员推送 ,001494 门店接车合作保险 ,001492 代堪到店 , 001490 门店接车非合作保险 , 001491 车险会员报案
        if (!Objects.equals("B",lossQuotation.getOrderType().getCode())) {
            switch (id) {
                case "001490":
                case "001494":
                    dividendStore = result.getDoubleValue("A005");
                    dividendPlatform =  result.getDoubleValue("A002");
                    dividendBase = Arith.round(1 - dividendStore - dividendPlatform,2);
                    break;
                case "001491":
                    dividendStore = result.getDoubleValue("A004");
                    dividendPlatform =  result.getDoubleValue("A001");
                    dividendBase = Arith.round(1 - dividendStore - dividendPlatform,2);
                    break;
                case "001492":
                case "001493":
                    dividendStore = result.getDoubleValue("A006");
                    dividendPlatform =  result.getDoubleValue("A003");
                    dividendBase = Arith.round(1 - dividendStore - dividendPlatform,2);
                    break;

                default:
                    dividendStore = 1;
                    dividendBase = 0;
                    dividendPlatform = 0;
            }
        }else {
            switch (id) {
                case "001490":
                case "001494":
                    dividendStore = result.getDoubleValue("A012");
                    dividendPlatform =  result.getDoubleValue("A002");
                    dividendBase = Arith.round(1 - dividendStore - dividendPlatform,2);
                    break;
                case "001491":
                    dividendStore = result.getDoubleValue("A011");
                    dividendPlatform =  result.getDoubleValue("A001");
                    dividendBase = Arith.round(1 - dividendStore - dividendPlatform,2);
                    break;
                case "001493":
                    dividendStore = result.getDoubleValue("A013");
                    dividendPlatform =  result.getDoubleValue("A003");
                    dividendBase = Arith.round(1 - dividendStore - dividendPlatform,2);
                    break;
                case "001492":
                    dividendStore = result.getDoubleValue("A014");
                    dividendPlatform =  result.getDoubleValue("A004");
                    dividendBase = Arith.round(1 - dividendStore - dividendPlatform,2);
                    break;
                default:
                    dividendStore = 1;
                    dividendBase = 0;
                    dividendPlatform = 0;
            }
        }

        lossQuotation.setDividendPlatform(dividendPlatform);
        lossQuotation.setDividendStore(dividendStore);
        lossQuotation.getLossQuotationPlans().forEach(lossQuotationPlan -> {
            lossQuotationPlan.setDividendStore(dividendStore);
            lossQuotationPlanRepository.saveAndFlush(lossQuotationPlan);
        });
        lossQuotation.setDividendBase(dividendBase);
    }

    /**
     * 获取委托定损业务费率
     * @param lossQuotation
     * @return
     */
    public JSONObject getCarDamageRate (LossQuotation lossQuotation) {
        PartyRole storeCompany = lossQuotation.getGetCarDept().getCompany();
        PartyRole serviceCompany = lossQuotation.getFixedLossDept().getCompany();
        String orderType = lossQuotation.getOrderType().getCode();
        String conditionStrategyId = "";
        switch (orderType) {
            case "A" :
                conditionStrategyId = "XS52";
                break;
            case "B" :
                conditionStrategyId = "DS01";
                break;
            default:
                throw new RuntimeException("没有该定损类型:" + orderType);
        }
        Map map = MapUtil.mapper(
                "COMPANY_ID", serviceCompany.getId(),
                "OPERATION", serviceCompany.getParty().getCorporate().getOperation().getId(),
                "KGSNX",Objects.equals(serviceCompany.getId(),storeCompany.getId()) ? 0:1,
                "SYS_RQ",new Date(),"conditionStrategyId", conditionStrategyId
        );
        Object obj = invoke("condition.execConditionStrategy", map);
        return new JSONObject(Objects.requireNonNull(MapUtil.mapped(obj)));
    }

    /**
     * 检测订单类型变化情况
     * @param lossQuotation
     */
    private void checkChangeOrderType(LossQuotation lossQuotation) {
        LossQuotation oldLossQuotation = lossQuotationRepository.findOne(lossQuotation.getId());
        String orderType = lossQuotation.getOrderType().getName();
        if (Objects.equals(orderType,"委托定损")) {
            checkInsuranceRule(lossQuotation.getInsuranceCompany(),lossQuotation.getFixedLossDept().getCompany());
        }
        if (!Objects.equals(orderType,oldLossQuotation.getOrderType().getName())) {
            switch (orderType) {
                case "委托定损" :
                    parsingDividendRatio(lossQuotation);
                    break;
                case "卖单模式" :
                    lossQuotation.setDividendBase(0);
                    lossQuotation.setDividendStore(0);
                    lossQuotation.setDividendPlatform(0);
                    break;
                default:
                    throw new RuntimeException("没有该定损类型:" + orderType);
            }
        }
    }

    /**
     * 凭证完成调用
     * @param lossQuotationId
     * @return
     */
    public LossQuotation lossQuotationVoucherComplete(String lossQuotationId){
        LossQuotation lossQuotation = lossQuotationRepository.findOne(lossQuotationId);
        if (lossQuotation==null)return null;
        lossQuotation.setPostDate(new Date());
        lossQuotation = lossQuotationRepository.saveAndFlush(lossQuotation);
        return lossQuotation;
    }

    /**
     * 完成分摊
     * @param lossQuotation
     */
    public void completeApportion(LossQuotation lossQuotation) {
        //待分摊回款
        List<LossReceivedItem> lossReceivedItemList = lossQuotation.getLossReceivedItem().stream().filter(item -> !item.isApportionComplete()).collect(Collectors.toList());
        if (lossReceivedItemList.size()==0) return;
        //查询已分摊零售单
        JSONObject apportionOrder = lossReceivedApportionService.findAllApportionOrder(lossQuotation);
        //分摊完成的单据
        List<String> apportionComplete = (List<String>) apportionOrder.get("apportionComplete");
        //未分摊完成的单据
        List<Map> unappropriated = (List<Map>) apportionOrder.get("unappropriated");
        //分摊中的零售单
        List<String> ids = unappropriated.stream().map(map -> (String) map.get("id")).collect(toList());
        ids.addAll(apportionComplete);
        //查询所有零售单并排除分摊
        List<RetailOrder> retailOrderList = SpringManager.getBean(RetailOrderRepository.class).findAll(JpaDsl.toCriteria("source","EQ", lossQuotation.getId(),"sourceBusinessType","NE","LossSaleAdjust"),new Sort(Sort.Direction.ASC, "createDate"))
                .stream().filter(retailOrder -> !ids.contains(retailOrder.getId())).collect(toList());
        //添加进未分摊完成
        unappropriated.addAll(retailOrderList.stream().map(retailOrder -> {
            return mapper(
                    "id", retailOrder.getId(), "type", retailOrder.getInnerBusinessType(),
                    "date", retailOrder.getDateApprove(),
                    "privateAmount", retailOrder.getPaymentMethodSet().stream()
                            .filter(retailOrderPayMethod -> retailOrderPayMethod.getPaymentMethodType().getId().equals("01"))
                            .mapToDouble(RetailOrderPayMethod::getAmount).sum(),
                    "amount", retailOrder.getPaymentMethodSet().stream()
                            .filter(retailOrderPayMethod -> !retailOrderPayMethod.getPaymentMethodType().getId().equals("01"))
                            .mapToDouble(RetailOrderPayMethod::getAmount).sum());
        }).collect(Collectors.toList()));
        //循环分摊未分摊完成的单据
        lossReceivedItemList.stream().filter(lossReceivedItem -> lossReceivedItem.getOperator()==null).map(item -> {
           lossReceivedApportionService.unappropriatedToComplete(item, unappropriated);
            return item;
        }).filter(item -> !item.isApportionComplete()).collect(toList());
        lossReceivedItemList.stream().filter(lossReceivedItem -> lossReceivedItem.getOperator()!=null).map(item -> {
            lossReceivedApportionService.appropriated(item, unappropriated);
            return item;
        }).filter(item -> !item.isApportionComplete()).collect(toList());
        lossQuotationRepository.saveAndFlush(lossQuotation);

    }

    public void writeAdjustmentAmount(LossQuotation lossQuotation) {
        List<LossReceivedApportion> apportionList = lossReceivedApportionService.findAllDT(mapper("id", lossQuotation.getId())).stream().filter(lossReceivedApportion -> !lossReceivedApportion.isFinish()).collect(toList());
        for (LossReceivedApportion dt : apportionList) {
            List<LossReceivedApportion> all = lossReceivedApportionRepository.findAll(JpaDsl.toCriteria(
                    "apportionOrder", "EQ", dt.getApportionOrder(),
                    "type", "EQ", "RO"
            )).stream().filter(l ->!l.isFinish()).collect(toList());

            double adjustmentAmount = dt.getUnappropriatedAmount();
            if (all.isEmpty()|| adjustmentAmount >0)return;
            for (LossReceivedApportion receivedApportion : all) {
                if (receivedApportion.getApportionAmount()+adjustmentAmount>0) {
                    receivedApportion.setAdjustmentAmount(adjustmentAmount);
                    adjustmentAmount=0;
                }else {
                    receivedApportion.setAdjustmentAmount(-1*receivedApportion.getApportionAmount());
                    adjustmentAmount+=receivedApportion.getApportionAmount();
//                    receivedApportion.setFinish(true);
                    lossReceivedApportionService.save(receivedApportion);
                }
            }
            if (adjustmentAmount==0){
                dt.setFinish(true);
                dt.setNeedApportionAmount(0);
                dt.setUnappropriatedAmount(0);
            }else {
                dt.setNeedApportionAmount(adjustmentAmount);
                dt.setUnappropriatedAmount(adjustmentAmount);

            }
            lossReceivedApportionService.save(dt);

        }
    }

    public JSONObject queryReceivedAmount(SimpleRequest request){
        JSONObject jo = request.getJO();
        String id = jo.getString("id");
        JSONObject result = new JSONObject();
        LossQuotation lossQuotation = lossQuotationRepository.findOne(id);
        //金额明细
        JSONObject receivedDetails = findReceivedDetails(lossQuotation);
//        //已结算金额
        JSONArray settleAmount = findSettleAmount(lossQuotation,receivedDetails);
//        //门店待回款请填写到账信息
        JSONArray storeWaitReceived = findWaitReceived(lossQuotation,receivedDetails,"store");
//        //平台待回款
        JSONArray platformWaitReceived = findWaitReceived(lossQuotation,receivedDetails,"platform");
//        //门店待缴款
        JSONArray storeWaitToPrepare = findStoreWaitToPrepare(lossQuotation,receivedDetails);
//
        result.put("receivedDetails",receivedDetails);
        result.put("settleAmount",settleAmount);
        result.put("storeWaitReceived",storeWaitReceived);
        result.put("platformWaitReceived",platformWaitReceived);
        result.put("storeWaitToPrepare",storeWaitToPrepare);
        // 服务方案明细中添加要货相关字段，用于前端显示控制
        LossQuotation format = lossQuotationFormat(lossQuotation);
        result.put("lossQuotationItems",format.getLossQuotationItems());
        return result;
    }

    public JSONObject queryReceivedDetail(SimpleRequest request){
        JSONObject jo = request.getJO();
        String id = jo.getString("id");
        String type = jo.getString("type");
        JSONObject result = new JSONObject();
        LossQuotation lossQuotation = lossQuotationRepository.findOne(id);
        //金额明细
        JSONObject receivedDetails = findReceivedDetails(lossQuotation);
        result.put("receivedDetails",receivedDetails);
        result.put("settleAmount",findSettleAmount(lossQuotation,receivedDetails));
        switch (type){
            case "settleAmount":
                //已结算金额

                break;
            case "storeWaitReceived":
                //门店待回款
                result.put(type,findWaitReceived(lossQuotation,receivedDetails,"store"));
                break;
            case "platformWaitReceived":
                //平台待回款
                result.put(type,findWaitReceived(lossQuotation,receivedDetails,"platform"));
                break;
            case "storeWaitToPrepare":
                //门店待缴款
                result.put(type,findStoreWaitToPrepare(lossQuotation,receivedDetails));
                break;
                default:throw new RuntimeException("错误类型:"+type);
        }


        return result;
    }

    private JSONObject findReceivedDetails(LossQuotation lossQuotation){
        JSONObject receivedDetails = new JSONObject();
        receivedDetails.put("realFixedLossAmount",lossQuotation.getInsuranceOffer()+lossQuotation.getAdjustAmount());
        receivedDetails.put("insuranceOffer",lossQuotation.getInsuranceOffer());
        receivedDetails.put("adjustAmount",lossQuotation.getAdjustAmount());
        return receivedDetails;
    }

    private JSONArray findSettleAmount(LossQuotation lossQuotation,JSONObject receivedDetails){
        String lossQuotationId = lossQuotation.getId();
        JSONArray result = lossQuotationDao.querySettleAmount(new JSONObject(mapper("id",lossQuotationId)));
        AtomicReference<Double> settleAmount = new AtomicReference<>((double) 0);
        AtomicReference<Double> storeWaitReceived = new AtomicReference<>((double) 0);
        AtomicReference<Double> platformWaitReceived = new AtomicReference<>((double) 0);
        AtomicReference<Double> storeWaitToPrepare = new AtomicReference<>((double) 0);
        result.forEach(o ->{
            JSONObject jsonObject = (JSONObject) o;
            double actual_total = jsonObject.getDoubleValue("ACTUAL_TOTAL");
            boolean b = actual_total > 0;
            settleAmount.set(settleAmount.get() + jsonObject.getDoubleValue("ADJUSTMENT_AMOUNT")+actual_total);
            storeWaitReceived.set(storeWaitReceived.get() + jsonObject.getDoubleValue("STOREWAITRECEIVED"));
            platformWaitReceived.set(platformWaitReceived.get() + jsonObject.getDoubleValue("PLATFORMWAITRECEIVED"));
            storeWaitToPrepare.set(storeWaitToPrepare.get() + jsonObject.getDoubleValue("STOREWAITTOPREPARE"));
        });
        receivedDetails.put("settleAmount",settleAmount.get());
        receivedDetails.put("waitSettleAmount",receivedDetails.getDoubleValue("realFixedLossAmount")-settleAmount.get());
        receivedDetails.put("storeWaitReceived",storeWaitReceived.get());
        receivedDetails.put("platformWaitReceived",platformWaitReceived.get());
        receivedDetails.put("storeWaitToPrepare",storeWaitToPrepare.get());
        return result;
    }

    private JSONArray findWaitReceived(LossQuotation lossQuotation, JSONObject receivedDetails,String type){
        String lossQuotationId = lossQuotation.getId();
        JSONArray result = new JSONArray();
        List<LossReceivedApportion> receivedApportions = lossReceivedApportionRepository.findAll(JpaDsl.toCriteria("lossQuotationId", "EQ", lossQuotationId),new Sort(Sort.Direction.ASC,"createDate"));
        AtomicReference<Double> realFixedLossAmount = new AtomicReference<>(receivedDetails.getDoubleValue("realFixedLossAmount"));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        receivedApportions.forEach(receivedApportion ->{
            JSONObject rowData = new JSONObject();
            LossReceivedItem lossReceivedItem = receivedApportion.getLossReceivedItem();
            if (type.equals("platform")&&((lossReceivedItem!=null&&lossReceivedItem.getAccountType().getId().equals("002033")))&&receivedApportion.getPaymentAmount()==0)return;
            rowData.put("postDate",receivedApportion.getReceivedDate()==null?null:sdf.format(receivedApportion.getReceivedDate()));
            rowData.put("createDate",sdf.format(receivedApportion.getCreateDate()));
            rowData.put("sourceOrderType",receivedApportion.getApportionOrderType());
            rowData.put("sourceOrder",receivedApportion.getApportionOrder());
            rowData.put("receivedDate",lossReceivedItem!=null?lossReceivedItem.getReceivedDate():null);
            rowData.put("accountType",lossReceivedItem!=null?lossReceivedItem.getAccountType().getDescription():null);
            double apportionAmount = receivedApportion.getApportionAmount();
//            if(apportionAmount==0)apportionAmount=-receivedApportion.getAdjustmentAmount();
            rowData.put("receivedAmount",apportionAmount);
            if (type.equals("platform")&&lossReceivedItem!=null&&lossReceivedItem.getAccountType().getId().equals("002033")){
                rowData.put("receivedAmount",receivedApportion.getPaymentAmount());
                rowData.put("receivedDate",lossReceivedItem.getReceivedDate());
                apportionAmount=receivedApportion.getPaymentAmount();
            }
            double finalApportionAmount = apportionAmount;
            if (receivedApportion.getType().equals("RO"))realFixedLossAmount.updateAndGet(v -> (double) (v - finalApportionAmount));
            rowData.put("waitReceivedAmount",realFixedLossAmount.get());
            rowData.put("serialNumber",lossReceivedItem!=null?lossReceivedItem.getSerialNumber():null);
            rowData.put("lossReceivedItemRemark",lossReceivedItem!=null?lossReceivedItem.getRemark():null);
            rowData.put("receivedRemark",receivedApportion.getRemark());

            result.add(rowData);
        });
        return result;
    }

    private JSONArray findStoreWaitToPrepare(LossQuotation lossQuotation,JSONObject receivedDetails){
        List<LossReceivedApportion> receivedApportions = lossReceivedApportionRepository.findAll(JpaDsl.toCriteria("lossQuotationId", "EQ", lossQuotation.getId(),"lossReceivedItem.accountType.id", "EQ", "002033"),new Sort(Sort.Direction.ASC,"createDate"));
        JSONArray result = new JSONArray();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        receivedApportions.forEach(receivedApportion ->{
            if (receivedApportion.getPaymentAmount()==receivedApportion.getApportionAmount())return;
            JSONObject rowData = new JSONObject();
            rowData.put("postDate",receivedApportion.getReceivedDate()==null?null:sdf.format(receivedApportion.getReceivedDate()));
            rowData.put("sourceOrderType",receivedApportion.getApportionOrderType());
            rowData.put("sourceOrder",receivedApportion.getApportionOrder());
            rowData.put("toPrepareAmount",receivedApportion.getApportionAmount()-receivedApportion.getPaymentAmount());
            rowData.put("paymentAmount",receivedApportion.getPaymentAmount());
            result.add(rowData);
        });
        return result;
    }



    /**
     * 判断定损方案的商品是否有库存
     * @param lossQuotation
     */
    private void checkProductStore(LossQuotation lossQuotation) {
        List classifyList = lossQuotation.getLossQuotationItems().stream().filter(item -> {
            Product product = item.getProduct();
            Classify classify = product.getClassify();
            //增加判断是否存在分类为M01010102.M0103，有价格无库存商品且未询价，有，则提交失败，并提示‘******有价格无库存，请转询价’
            return Objects.isNull(item.getServicePlan()) && (!item.isProductRule()) && !productNegativeSellingService.isProductNegativeSelling(product.getId()) && StringUtils.isEmpty(item.getOldInquiryNumber()) && item.getSalePrice() != 0  && (classify.getId().startsWith("M01010102") || classify.getId().startsWith("M0103"));
        }).filter(servicePlanItem -> LogicalUtil.notIn(servicePlanItem.getPriceForward(),"1","2","4","5")).map(item -> {return MapUtil.mapper("productId",item.getProduct().getId());}).collect(Collectors.toList());

        if( classifyList.size() !=0){
            JSONObject json = new JSONObject();
            Dept fixedLossDept = null;
            if (Objects.equals("B",lossQuotation.getOrderType().getCode())) {
                fixedLossDept = lossQuotation.getGetCarDept();
            }else {
                fixedLossDept = lossQuotation.getFixedLossDept();
            }
            if (Objects.isNull(fixedLossDept)) throw new RuntimeException("请检查接车门店！");
            json.put("NEW_DEPT_ID", fixedLossDept.getId());
            json.put("OLD_DEPT_ID", fixedLossDept.getOrigin());
            json.put("productList", classifyList);
            JSONArray array = servicePlanDao.queryProductStoreForList(json);

            JSONArray resultList = array.stream().filter(tempJson ->{
                JSONObject item = (JSONObject)tempJson;
                return item.getDoubleValue("GENERAL_STOCK") + item.getDoubleValue("SUB_STOCK") + item.getDoubleValue("STOCK_AMOUNT") <= 0;
            }).collect(Collectors.toCollection(JSONArray :: new));

            if(resultList.size() != 0)  throw new RuntimeException(resultList.getJSONObject(0).getString("NAME") + ",有价格无库存，请转询价");
        }
    }

    public JSONArray findLossInfo(SimpleRequest request){
        JSONObject jo = request.getJO();
        String key = jo.getString("key");
        JSONArray jsonArray = lossQuotationDao.queryLossInfo(jo);
        return jsonArray;

    }

    public LossQuotation lossQuotationFormat(LossQuotation lossQuotation){
        //获取要货明细
        List<ProductRequireItem> items = new ArrayList<>();
        productRequireRepository.findAllBySource(lossQuotation.getId())
                .stream()
                .filter(productRequire -> !productRequire.getState().equals("delete"))
                .map(ProductRequire::getProductRequireItems)
                .forEach(items::addAll);
        Map<String, List<ProductRequireItem>> products = items.stream().collect(groupingBy(productRequireItem -> productRequireItem.getProduct().getId()));

        lossQuotation.getLossQuotationItems().forEach(lossQuotationItem -> {
            Product product = lossQuotationItem.getProduct();
            if (!product.getProductGroup().getId().equals("10"))return;
            List<ProductRequireItem> productRequireItems = products.get(product.getId());
            if (productRequireItems==null||productRequireItems.isEmpty()) return;
            for (ProductRequireItem productRequireItem : productRequireItems) {
                //要货单明细
                ProductRequire productRequire = productRequireItem.getProductRequire();
                if (productRequire.getState().equals("create")){
                    lossQuotationItem.setRequireQtyId(productRequire.getId());
                    lossQuotationItem.setRequireQtyTempState("create");
                }
                if (productRequire.getState().equals("approve") && !lossQuotationItem.getRequireQtyTempState().equals("create")){
                    lossQuotationItem.setRequireQtyTempState("approve");
                }
                lossQuotationItem.addRequireQtyTemp(productRequireItem.getQtyRequire());
            }
        });
        return lossQuotation;
    }

    /**
     * 进入要货单菜单
     * @param re
     * @return
     */
    public ProductRequire toRequireFrom(SimpleRequest re){
        JSONObject jo = re.getJO();
        String id = jo.getString("requireQtyId");
        if (id == null) throw new RuntimeException("未查询到要货单编号！");
        return productRequireRepository.findOne(id);
    }

    private Object searchChangeCondition(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONArray condition = jo.getJSONArray("condition");
        JSONArray newCondition = new JSONArray();
        for (Object o : condition) {
//            if (o instanceof HashMap)continue;//HashMap格式的一般是权限条件 前端条件是JSON
            if (!(o instanceof JSONObject)){
                newCondition.add(o);
                continue;
            }
            JSONObject jsonObject = (JSONObject) o;
            switch (jsonObject.getString("field")) {
                case "terminal":
                    break;
                default:
                    newCondition.add(jsonObject);
            }
        }
        jo.put("condition",newCondition);
        return jo;
    }
}

